当前位置:首页 > JavaScript

链表js实现

2026-02-01 06:36:11JavaScript

链表的基本概念

链表是一种线性数据结构,由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。与数组不同,链表在内存中是非连续存储的,插入和删除操作的时间复杂度为 O(1),但访问元素的时间复杂度为 O(n)。

单向链表的实现

单向链表是最简单的链表形式,每个节点只有一个指针指向下一个节点。

class ListNode {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
}

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

  // 在链表末尾添加节点
  append(data) {
    const newNode = new ListNode(data);
    if (!this.head) {
      this.head = newNode;
    } else {
      let current = this.head;
      while (current.next) {
        current = current.next;
      }
      current.next = newNode;
    }
    this.size++;
  }

  // 在指定位置插入节点
  insertAt(data, index) {
    if (index < 0 || index > this.size) return false;
    const newNode = new ListNode(data);
    if (index === 0) {
      newNode.next = this.head;
      this.head = newNode;
    } else {
      let current = this.head;
      let prev = null;
      let i = 0;
      while (i < index) {
        prev = current;
        current = current.next;
        i++;
      }
      newNode.next = current;
      prev.next = newNode;
    }
    this.size++;
    return true;
  }

  // 删除指定位置的节点
  removeAt(index) {
    if (index < 0 || index >= this.size) return null;
    let removedNode;
    if (index === 0) {
      removedNode = this.head;
      this.head = this.head.next;
    } else {
      let current = this.head;
      let prev = null;
      let i = 0;
      while (i < index) {
        prev = current;
        current = current.next;
        i++;
      }
      removedNode = current;
      prev.next = current.next;
    }
    this.size--;
    return removedNode.data;
  }

  // 获取指定位置的数据
  getAt(index) {
    if (index < 0 || index >= this.size) return null;
    let current = this.head;
    let i = 0;
    while (i < index) {
      current = current.next;
      i++;
    }
    return current.data;
  }

  // 打印链表
  print() {
    let current = this.head;
    let result = [];
    while (current) {
      result.push(current.data);
      current = current.next;
    }
    console.log(result.join(' -> '));
  }
}

双向链表的实现

双向链表每个节点有两个指针,分别指向前一个节点和后一个节点,便于双向遍历。

链表js实现

class DoublyListNode {
  constructor(data) {
    this.data = data;
    this.prev = null;
    this.next = null;
  }
}

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

  // 在链表末尾添加节点
  append(data) {
    const newNode = new DoublyListNode(data);
    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.prev = this.tail;
      this.tail.next = newNode;
      this.tail = newNode;
    }
    this.size++;
  }

  // 在指定位置插入节点
  insertAt(data, index) {
    if (index < 0 || index > this.size) return false;
    const newNode = new DoublyListNode(data);
    if (index === 0) {
      if (!this.head) {
        this.head = newNode;
        this.tail = newNode;
      } else {
        newNode.next = this.head;
        this.head.prev = newNode;
        this.head = newNode;
      }
    } else if (index === this.size) {
      newNode.prev = this.tail;
      this.tail.next = newNode;
      this.tail = newNode;
    } else {
      let current = this.head;
      let i = 0;
      while (i < index) {
        current = current.next;
        i++;
      }
      newNode.prev = current.prev;
      newNode.next = current;
      current.prev.next = newNode;
      current.prev = newNode;
    }
    this.size++;
    return true;
  }

  // 删除指定位置的节点
  removeAt(index) {
    if (index < 0 || index >= this.size) return null;
    let removedNode;
    if (index === 0) {
      removedNode = this.head;
      if (this.size === 1) {
        this.head = null;
        this.tail = null;
      } else {
        this.head = this.head.next;
        this.head.prev = null;
      }
    } else if (index === this.size - 1) {
      removedNode = this.tail;
      this.tail = this.tail.prev;
      this.tail.next = null;
    } else {
      let current = this.head;
      let i = 0;
      while (i < index) {
        current = current.next;
        i++;
      }
      removedNode = current;
      current.prev.next = current.next;
      current.next.prev = current.prev;
    }
    this.size--;
    return removedNode.data;
  }

  // 打印链表
  print() {
    let current = this.head;
    let result = [];
    while (current) {
      result.push(current.data);
      current = current.next;
    }
    console.log(result.join(' <-> '));
  }
}

链表的使用示例

// 单向链表示例
const list = new LinkedList();
list.append(10);
list.append(20);
list.append(30);
list.insertAt(15, 1);
list.print(); // 输出: 10 -> 15 -> 20 -> 30
list.removeAt(2);
list.print(); // 输出: 10 -> 15 -> 30

// 双向链表示例
const dList = new DoublyLinkedList();
dList.append(10);
dList.append(20);
dList.append(30);
dList.insertAt(15, 1);
dList.print(); // 输出: 10 <-> 15 <-> 20 <-> 30
dList.removeAt(2);
dList.print(); // 输出: 10 <-> 15 <-> 30

链表的应用场景

链表适用于需要频繁插入和删除操作的场景,如实现队列、栈、哈希表的链地址法等。由于其动态内存分配的特性,链表在内存利用率上比数组更灵活。

标签: 链表js
分享给朋友:

相关文章

js实现目录

js实现目录

实现目录的基本思路 在JavaScript中实现目录功能通常涉及以下几个核心步骤:解析文档中的标题元素(如h1-h6),动态生成目录结构,并添加交互逻辑(如点击跳转)。以下是具体实现方法: 解析标题…

js实现图片

js实现图片

图片加载与显示 在JavaScript中,可以通过Image对象动态加载图片。创建实例后设置src属性触发加载,通过onload回调处理加载完成后的操作: const img = new Ima…

js验证码的实现

js验证码的实现

验证码的基本实现原理 验证码(CAPTCHA)的核心目标是区分人类用户和自动化程序。JavaScript可用于生成或验证客户端验证码,但需注意纯前端验证可能被绕过,通常需结合后端验证。 纯前端验证码…

js进度条实现

js进度条实现

使用HTML和CSS创建基础结构 在HTML中创建一个容器元素用于显示进度条,通常使用<div>元素。CSS用于设置进度条的样式,包括宽度、高度、颜色和圆角等属性。 <div cl…

js实现隐藏div

js实现隐藏div

隐藏div的几种方法 使用JavaScript隐藏div元素可以通过多种方式实现,以下是几种常见的方法: 方法一:修改style.display属性 将div的display属性设置为"none"…

vue js实现弹窗

vue js实现弹窗

Vue.js 实现弹窗的方法 使用组件实现弹窗 创建一个独立的弹窗组件,例如 Modal.vue,包含弹窗的 HTML 结构和样式。在组件中定义 props 控制弹窗的显示与隐藏。 <temp…