返回

链表类在JavaScript的演变:从零到通透

前端

从零开始,用JavaScript构建链表类

在JavaScript中,没有栈、队列、链表等明显的结构,但我们可以利用对象伪造这些结构。这次,我们将用对象构建链表相关类:单向链表、有序链表、循环链表和双向链表。

1. 单向链表

单向链表是最基本也是最常见的链表。它由一系列节点组成,每个节点包含一个值和指向下一个节点的指针。

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

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

  append(value) {
    const newNode = new Node(value);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
    }
    this.length++;
  }

  prepend(value) {
    const newNode = new Node(value);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.next = this.head;
      this.head = newNode;
    }
    this.length++;
  }

  insert(value, index) {
    if (index === 0) {
      this.prepend(value);
    } else if (index >= this.length) {
      this.append(value);
    } else {
      const newNode = new Node(value);
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      newNode.next = current.next;
      current.next = newNode;
      this.length++;
    }
  }

  remove(index) {
    if (index === 0) {
      this.head = this.head.next;
      if (this.head === null) {
        this.tail = null;
      }
    } else if (index >= this.length - 1) {
      let current = this.head;
      while (current.next !== this.tail) {
        current = current.next;
      }
      current.next = null;
      this.tail = current;
    } else {
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      current.next = current.next.next;
      this.length--;
    }
    this.length--;
  }

  get(index) {
    if (index >= this.length) {
      return undefined;
    }
    let current = this.head;
    for (let i = 0; i < index; i++) {
      current = current.next;
    }
    return current.value;
  }

  set(value, index) {
    if (index >= this.length) {
      return undefined;
    }
    let current = this.head;
    for (let i = 0; i < index; i++) {
      current = current.next;
    }
    current.value = value;
  }

  print() {
    let current = this.head;
    while (current) {
      console.log(current.value);
      current = current.next;
    }
  }
}

const list = new LinkedList();
list.append(1);
list.append(2);
list.append(3);
list.prepend(0);
list.insert(4, 2);
list.remove(2);
list.set(5, 2);
list.get(2);
list.print();

2. 有序链表

有序链表是一种特殊的单向链表,其节点按值升序排列。

class SortedLinkedList extends LinkedList {
  constructor() {
    super();
  }

  append(value) {
    if (this.head === null) {
      this.head = new Node(value);
      this.tail = this.head;
    } else {
      let current = this.head;
      while (current.next !== null && value > current.value) {
        current = current.next;
      }
      if (value <= current.value) {
        const newNode = new Node(value);
        newNode.next = current;
        if (current === this.head) {
          this.head = newNode;
        } else {
          let previous = this.head;
          while (previous.next !== current) {
            previous = previous.next;
          }
          previous.next = newNode;
        }
      } else {
        const newNode = new Node(value);
        newNode.next = current.next;
        current.next = newNode;
        if (newNode.next === null) {
          this.tail = newNode;
        }
      }
    }
    this.length++;
  }

  insert(value, index) {
    if (index === 0) {
      this.prepend(value);
    } else if (index >= this.length) {
      this.append(value);
    } else {
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      const newNode = new Node(value);
      newNode.next = current.next;
      current.next = newNode;
      this.length++;
    }
  }
}

const sortedList = new SortedLinkedList();
sortedList.append(1);
sortedList.append(2);
sortedList.append(3);
sortedList.prepend(0);
sortedList.insert(4, 2);
sortedList.remove(2);
sortedList.set(5, 2);
sortedList.get(2);
sortedList.print();

3. 循环链表

循环链表是一种特殊的单向链表,其最后一个节点指向第一个节点,形成一个环。

class CircularLinkedList extends LinkedList {
  constructor() {
    super();
  }

  append(value) {
    const newNode = new Node(value);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
      newNode.next = this.head;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
      newNode.next = this.head;
    }
    this.length++;
  }

  prepend(value) {
    const newNode = new Node(value);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
      newNode.next = this.head;
    } else {
      newNode.next = this.head;
      this.head = newNode;
      this.tail.next = this.head;
    }
    this.length++;
  }
}

const circularList = new CircularLinkedList();
circularList.append(1);
circularList.append(2);
circularList.append(3);
circularList.prepend(0);
circularList.remove(2);
circularList.set(5, 2);
circularList.get(2);
circularList.print();

4. 双向链表

双向链表是一种特殊的链表,其节点除了指向下一个节点外,还指向上一个节点。

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

  append(value) {
    const newNode = new Node(value);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      newNode.prev = this.tail;
      this.tail = newNode;
    }
    this.length++;
  }

  prepend(value) {
    const newNode = new Node(value);
    if (