JavaScript 中的链表:理解和应用

链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在 JavaScript 中,我们可以使用对象来实现链表。今天哈士奇将向大家介绍链表的基本概念、常见操作以及在 JavaScript 中如何实现链表。

什么是链表?

链表是一种线性数据结构,与数组不同,链表中的元素在内存中不必相连。每个节点包含两部分:数据和指针。数据存储节点的值,指针指向下一个节点。

链表的种类

  1. 单向链表(Singly Linked List):每个节点只有一个指针,指向下一个节点。
  2. 双向链表(Doubly Linked List):每个节点有两个指针,分别指向前一个节点和后一个节点。
  3. 循环链表(Circular Linked List):尾节点的指针指向头节点,形成一个循环。

链表的优点

  1. 动态大小:链表的大小可以动态增加或减少,不像数组需要预先分配固定大小的空间。
  2. 插入和删除高效:在链表中插入或删除元素时,只需要调整节点的指针,时间复杂度为 O(1),而在数组中插入或删除元素的时间复杂度为 O(n)。
  3. 内存空间利用率高:链表在内存中分配的空间可以比数组更灵活,不会出现内存浪费的情况。
  4. 支持循环操作:循环链表可以支持循环操作,例如轮流访问每个节点。

因此,链表在需要频繁插入和删除元素、或者不确定数据量大小的情况下具有很大的优势。

链表实现

单向链表示例

在 JavaScript 中,我们可以使用对象来表示节点,使用指针来连接节点。下面是一个简单的单向链表实现示例:

javascript 复制代码
class Node {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

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

  add(data) {
    const node = new Node(data);
    let current;

    if (this.head == null) {
      this.head = node;
    } else {
      current = this.head;

      while (current.next) {
        current = current.next;
      }

      current.next = node;
    }

    this.size++;
  }

  insertAt(data, index) {
    if (index > 0 && index > this.size) {
      return false;
    } else {
      const node = new Node(data);
      let current, previous;

      current = this.head;

      if (index === 0) {
        node.next = head;
        this.head = node;
      } else {
        current = this.head;
        let i = 0;

        while (i < index) {
          i++;
          previous = current;
          current = current.next;
        }

        node.next = current;
        previous.next = node;
      }

      this.size++;
    }
  }

  removeFrom(index) {
    if (index > 0 && index > this.size) {
      return -1;
    } else {
      let current, previous, i = 0;
      current = this.head;
      previous = current;

      if (index === 0) {
        this.head = current.next;
      } else {
        while (i < index) {
          i++;
          previous = current;
          current = current.next;
        }

        previous.next = current.next;
      }

      this.size--;

      return current.data;
    }
  }

  // 其他操作方法:isEmpty、sizeOfList、printList
}

双向链表示例

双向链表与单向链表类似,但每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。下面是一个简单的双向链表实现示例:

javascript 复制代码
class Node {
  constructor(data) {
    this.data = data;
    this.prev = null;
    this.next = null;
  }
}

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

  add(data) {
    const node = new Node(data);

    if (this.head === null) {
      this.head = node;
      this.tail = node;
    } else {
      this.tail.next = node;
      node.prev = this.tail;
      this.tail = node;
    }

    this.size++;
  }

  // 其他操作方法:insertAt、removeFrom、isEmpty、sizeOfList、printList
}

循环链表示例

循环链表与单向链表类似,但尾节点的指针指向头节点,形成一个循环。下面是一个简单的循环链表实现示例:

javascript 复制代码
class Node {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

class CircularLinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }

  add(data) {
    const node = new Node(data);

    if (this.head === null) {
      this.head = node;
      this.tail = node;
      this.tail.next = this.head;
    } else {
      node.next = this.head;
      this.tail.next = node;
      this.tail = node;
    }

    this.size++;
  }

  // 其他操作方法:insertAt、removeFrom、isEmpty、sizeOfList、printList
}

链表的应用

链表在计算机科学中有许多应用。其中一些常见的应用包括:

  1. 实现堆栈(Stack)和队列(Queue):链表可以用来实现这两种数据结构。
  2. 内存分配:操作系统中的内存管理器使用链表来跟踪可用和已分配的内存块。
  3. 图形图像:链表可以用来表示图形图像中的路径。

总结

链表是一种灵活的数据结构,具有许多应用场景。在 JavaScript 中,我们可以使用对象和指针来实现链表,并实现常见的链表操作。通过理解链表的基本概念和实现方法,我们可以更好地应用它们解决实际问题。今天你学会了嘛?

相关推荐
To_OC21 小时前
LC 239 滑动窗口最大值:从暴力超时到单调队列一遍过
javascript·算法·leetcode
To_OC21 小时前
从一行入口代码啃透 NestJS:工厂模式、装饰器和依赖注入是怎么串起来的
后端·设计模式·nestjs
Python私教21 小时前
多个项目怎么安全合并?先适配,再切换
后端·python·架构
Mh1 天前
虚拟滚动真的比普通滚动性能更好吗?
前端·javascript·性能优化
.道阻且长.1 天前
9.LeetCode算法习题讲解--滑动窗口--无重复字符的最长字串
算法·leetcode·职场和发展·哈希算法
Python私教1 天前
从表格到管理系统:别先写页面,先补齐权限、流程和审计
数据库·后端·架构
ltl1 天前
HNSW:图索引如何击败树索引
算法
北斗落凡尘1 天前
LangGraph 入门实战(12)--使用MCP
后端·python·langchain
曹牧1 天前
C#:数字的定义和表示方式
算法·c#
kyriewen1 天前
我把 AI 写的并发请求控制器手写了一遍——3 个语义我当时根本讲不清
前端·javascript·面试