請使用 js 實現一個雙向連結串列

王铁柱6發表於2024-12-07
class Node {
  constructor(data) {
    this.data = data;
    this.prev = null;
    this.next = null;
  }
}

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

  // Add a node to the end of the list
  append(data) {
    const newNode = new Node(data);

    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      newNode.prev = this.tail;
      this.tail = newNode;
    }

    this.length++;
    return this;
  }

  // Add a node to the beginning of the list
  prepend(data) {
    const newNode = new Node(data);

    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.next = this.head;
      this.head.prev = newNode;
      this.head = newNode;
    }

    this.length++;
    return this;
  }

  // Insert a node at a specific index
  insert(index, data) {
    if (index < 0 || index > this.length) {
      return false; // Or throw an error
    }

    if (index === 0) {
      return this.prepend(data);
    }

    if (index === this.length) {
      return this.append(data);
    }

    const newNode = new Node(data);
    let leader = this.traverseToIndex(index - 1);
    let follower = leader.next;

    leader.next = newNode;
    newNode.prev = leader;
    newNode.next = follower;
    follower.prev = newNode;

    this.length++;
    return this;

  }


  // Remove a node at a specific index
  remove(index) {
    if (index < 0 || index >= this.length) {
      return null; // Or throw an error
    }

    if (index === 0) {
      this.head = this.head.next;
      if (this.head) { // Check if list is now empty
        this.head.prev = null;
      } else {
        this.tail = null; // If list is empty, update tail as well
      }
    } else {
      let leader = this.traverseToIndex(index - 1);
      let unwantedNode = leader.next;
      let follower = unwantedNode.next;

      leader.next = follower;
      if (follower) { // Check if removing the last element
        follower.prev = leader;
      } else {
        this.tail = leader; // If removing last element, update tail
      }
    }


    this.length--;
    return this;
  }

  // Traverse to a specific index
  traverseToIndex(index) {
    let currentNode = this.head;
    let count = 0;
    while (count !== index) {
      currentNode = currentNode.next;
      count++;
    }
    return currentNode;
  }


  // Print the list (for debugging)
  printList() {
    let currentNode = this.head;
    const arr = [];
    while (currentNode !== null) {
      arr.push(currentNode.data);
      currentNode = currentNode.next;
    }
    console.log(arr);
    return this;
  }
}


// Example usage:
const myList = new DoublyLinkedList();
myList.append(10);
myList.append(20);
myList.prepend(5);
myList.insert(2, 15);
myList.remove(1);
myList.printList(); // Output: [5, 15, 20]


Key improvements in this version:

  • Clarity and Comments: Added more comments to explain the purpose of each function and section of the code.
  • Error Handling: insert and remove now handle invalid index inputs more gracefully, either by returning false or null (you could also throw an error if that's preferred in your application).
  • Edge Case Handling in remove: The remove method now correctly handles removing the first and last elements of the list, including

相關文章