返回

前端进阶之单向与双向链表的实现

前端

链表是一种非连续的线性数据结构,它由一系列的节点组成,每个节点包含一个数据域和一个指针域。指针域指向下一个节点,数据域存储着该节点的数据。链表的特点是,它可以在任意位置插入或删除数据,而不需要移动整个链表。

单向链表是一种最基本的链表,它只允许从一个节点向前遍历到下一个节点。双向链表则允许从一个节点向前或向后遍历到另一个节点。双向链表比单向链表更灵活,但实现起来也更复杂。

单向链表的实现

单向链表的实现非常简单,只需要定义一个节点类,然后就可以根据需要创建节点并将其连接起来。以下是一个单向链表的实现示例:

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

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

  add(data) {
    const node = new Node(data);
    if (this.head === null) {
      this.head = node;
      this.tail = node;
    } else {
      this.tail.next = node;
      this.tail = node;
    }
  }

  remove(data) {
    if (this.head === null) {
      return;
    }

    if (this.head.data === data) {
      this.head = this.head.next;
      if (this.head === null) {
        this.tail = null;
      }
      return;
    }

    let current = this.head;
    let previous = null;

    while (current !== null) {
      if (current.data === data) {
        previous.next = current.next;
        if (current === this.tail) {
          this.tail = previous;
        }
        return;
      }

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

  find(data) {
    if (this.head === null) {
      return null;
    }

    let current = this.head;

    while (current !== null) {
      if (current.data === data) {
        return current;
      }

      current = current.next;
    }

    return null;
  }

  print() {
    if (this.head === null) {
      console.log('链表为空');
      return;
    }

    let current = this.head;

    while (current !== null) {
      console.log(current.data);
      current = current.next;
    }
  }
}

双向链表的实现

双向链表的实现比单向链表复杂一些,但思路基本相同。双向链表的节点需要有两个指针域,分别指向下一个节点和上一个节点。以下是一个双向链表的实现示例:

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

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

  add(data) {
    const node = new Node(data);
    if (this.head === null) {
      this.head = node;
      this.tail = node;
    } else {
      this.tail.next = node;
      node.previous = this.tail;
      this.tail = node;
    }
  }

  remove(data) {
    if (this.head === null) {
      return;
    }

    if (this.head.data === data) {
      this.head = this.head.next;
      if (this.head === null) {
        this.tail = null;
      } else {
        this.head.previous = null;
      }
      return;
    }

    if (this.tail.data === data) {
      this.tail = this.tail.previous;
      if (this.tail === null) {
        this.head = null;
      } else {
        this.tail.next = null;
      }
      return;
    }

    let current = this.head;

    while (current !== null) {
      if (current.data === data) {
        current.previous.next = current.next;
        current.next.previous = current.previous;
        return;
      }

      current = current.next;
    }
  }

  find(data) {
    if (this.head === null) {
      return null;
    }

    let current = this.head;

    while (current !== null) {
      if (current.data === data) {
        return current;
      }

      current = current.next;
    }

    return null;
  }

  print() {
    if (this.head === null) {
      console.log('链表为空');
      return;
    }

    let current = this.head;

    while (current !== null) {
      console.log(current.data);
      current = current.next;
    }
  }
}

时间复杂度和空间复杂度

单向链表和双向链表的时间复杂度和空间复杂度都是O(n),其中n是链表中的节点数。

单向链表和双向链表的空间复杂度都是O(n),其中n是链表中的节点数。