JavaScript数据结构与算法之链表

JavaScript数据结构与算法之链表

什么是链表

链表是一种线性数据结构,它由一个一个的节点组成,每个节点包含两个部分:当前节点存储的数据,以及指向下一个节点的指针。相比于数组,链表可以实现更加灵活的内存分配,可以动态增加或删除节点,但访问链表中的节点比访问数组要慢。

单向链表

单向链表是最简单的一种链表,它每个节点只有一个指针,指向它的下一个节点。单向链表的尾部节点指针为null,表示链表的结束。

下面是一个单向链表的节点结构的定义:

class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
  }
}

整个链表可以通过第一个节点来访问:

class LinkedList {
  constructor() {
    this.head = null;
  }

  traverse() {
    let curr = this.head;
    while (curr != null) {
      console.log(curr.val);
      curr = curr.next;
    }
  }
}

在一个空链表中插入节点:

const linkedList = new LinkedList();

linkedList.head = new Node(1);
linkedList.head.next = new Node(2);
linkedList.head.next.next = new Node(3);

linkedList.traverse();  // 输出1, 2, 3

在链表尾部添加节点:

const linkedList = new LinkedList();

if (linkedList.head == null) {
  linkedList.head = new Node(1);
} else {
  let curr = linkedList.head;
  while (curr.next != null) {
    curr = curr.next;
  }
  curr.next = new Node(2);
}

linkedList.traverse();  // 输出1, 2

双向链表

双向链表每个节点除了指向下一个节点的指针之外,还有指向上一个节点的指针。双向链表可以方便地反向遍历链表,但同时也需要更多的内存空间来存储指向上一个节点的指针。

下面是一个双向链表的节点结构的定义:

class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
    this.prev = null;
  }
}

双向链表的插入和删除节点与单向链表基本相同,只是需要同时更新新节点和旧节点的指针。

下面是一个在双向链表中插入新节点的例子:

class DoublyLinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
  }

  append(val) {
    const newNode = new Node(val);
    if (this.head == null) {  // 为空链表
      this.head = newNode;
      this.tail = newNode;
    } else {  // 不为空链表
      newNode.prev = this.tail;
      this.tail.next = newNode;
      this.tail = newNode;
    }
  }
}

const doublyLinkedList = new DoublyLinkedList();

doublyLinkedList.append(1);  // 在尾部添加1
doublyLinkedList.append(2);  // 在尾部添加2
doublyLinkedList.append(3);  // 在尾部添加3

let curr = doublyLinkedList.tail;
while (curr != null) {
  console.log(curr.val);
  curr = curr.prev;
}
// 输出 3, 2, 1

链表优化

链表与数组不同,在获取链表中第n个元素时,需要从链表的头部逐步遍历到第n个元素。因此,如果我们需要频繁地获取链表中的第n个元素,链表的效率就会变得非常低下。

为了避免这种情况,可以在链表中加入一个缓存,用来存储访问过的节点,下次再访问相同节点时就可以直接从缓存中获取,而无需遍历整个链表。这种缓存又称之为LRU缓存。

除了LRU缓存之外,还可以使用其他一些技巧来优化链表,例如使用哨兵节点、使用虚拟头节点等。

小结

链表作为一种经典的数据结构,用来解决一些传统的算法问题非常方便。此外,在编写一些特殊的数据结构时,例如跳表等,也会经常用到链表。

链表的应用非常广泛,而且难度适中,非常适合作为入门算法训练的练习题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript数据结构与算法之链表 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 简单讲解哈希表

    哈希表(Hash Table),也被称为散列表,是一种高效的数据结构,它可以在O(1)的时间复杂度下完成插入、删除、查找等基本操作。哈希表是通过将关键字映射到一个固定大小的表中来实现的,这个映射函数被称为哈希函数。 什么是哈希函数 哈希函数是将任意长度的输入值(也称为“键”或“关键字”)映射为固定大小的输出值(也称为“哈希值”或“散列”)。哈希函数必须将不同…

    数据结构 2023年5月17日
    00
  • C++数据结构AVL树全面分析

    C++数据结构AVL树全面分析 简介 AVL树是一种二叉搜索树,它通过使树保持高度平衡来提高搜索、插入和删除操作的效率。AVL树本质上是通过在插入和删除节点时旋转子树来保持平衡的。AVL树被认为是最早的自平衡二元搜索树。 AVL树的定义 AVL树是一种满足以下特性的BST: 每个节点都有一个左子树和一个右子树,并且左子树、右子树也是AVL树。 左子树高度和右…

    数据结构 2023年5月17日
    00
  • 一、对系统理论的认识

           经过一周的时间学习,我们知道了系统的定义:是一个由一组相互连接的要素构成的,能够实现某个目标的整体,任何一个系统都包括三种构成要件:要素连接,功能或目标。       1.系统的连接使得系统呈现特定的结构,使得系统的各个部件连接而产生系统特有的功能—相关性导新功能涌现。连接的媒介—“三流”(信息流,能量流,物质流)。       2.系统的静态…

    算法与数据结构 2023年4月18日
    00
  • Java数据结构之图的路径查找算法详解

    Java数据结构之图的路径查找算法详解 什么是图? 在计算机科学中,图是一种非常常见的数据结构,用于表示图形和网络等概念。图由节点和边组成,其中节点表示实体,边表示这些实体之间的关系。节点和边可以表示各种各样的实体和关系,因此图在计算机科学中具有广泛的应用。 图的路径查找算法 路径查找算法是一个用途广泛的算法,它用于查找从一个节点到另一个节点的路径。在图中,…

    数据结构 2023年5月17日
    00
  • C语言数据结构二叉树简单应用

    C语言数据结构二叉树简单应用攻略 1. 什么是二叉树? 二叉树(Binary Tree)是一种树形结构,它的每个节点最多包含两个子节点,它是非线性数据结构,可以用来表示许多问题,例如家族关系、计算机文件系统等等。 2. 二叉树的基本操作 二叉树的基本操作包括插入、删除、查找等等,本攻略主要讲解插入和查找的实现。 插入操作的代码如下: // 二叉树的插入操作 …

    数据结构 2023年5月17日
    00
  • C语言数据结构实现字符串分割的实例

    C语言中数据结构实现字符串分割可以用到两种常见数据结构:指针和数组。 方法一:指针 步骤一:创建指针 首先声明一个指针类型的变量,用来存储字符串中单个字符所在的地址: char *ptr; 步骤二:遍历字符串 通过对字符串进行遍历,在每个分隔符位置上获取单词,并通过指针记录下每个单词的地址: char str[] = "C语言-数据结构-字符串分割…

    数据结构 2023年5月17日
    00
  • C数据结构之双链表详细示例分析

    作为本网站的作者,我很高兴为你讲解C数据结构之双链表详细示例分析的完整攻略。 双链表简介与定义 双链表是链表的一种,在链表中每一个节点都有一个指针域,指向下一个节点,这个指针域称为next指针;而在双链表中每一个节点也有两个指针域,一个指向前驱节点,另一个指向后继节点,即prev指针与next指针。由于双链表存在两个指针域,因此它支持双向遍历,无论是正向还是…

    数据结构 2023年5月17日
    00
  • ecnuoj 5042 龟速飞行棋

    5042. 龟速飞行棋 题目链接:5042. 龟速飞行棋 赛中没过,赛后补题时由于题解有些抽象,自己写个题解。 可以发现每次转移的结果只跟后面两个点的胜负状态有关。 不妨设 \(f_{u,a,b}\) 表示,\(u+1\) 号点的胜负态为 \(a\),\(u+2\) 号点的胜负态为 \(b\),此时从 \(1\) 号点出发的胜负态是什么。那么可以发现,利用 …

    算法与数据结构 2023年4月17日
    00
合作推广
合作推广
分享本页
返回顶部