JavaScript数据结构与算法之双向链表

26 阅读1分钟
// 双向链表
// 双向链表 相对于单向链表,可以正反两头进行遍历
// 根据下标获取元素时,可以根据下标及链表长度进行判断 -->>正向遍历/反向遍历
function DoublyLinkedList() {
  // 内置方法
  function Node(element) {
    this.element = element;
    this.prev = null;
    this.next = null;
  }
  // 内置属性
  this.length = 0;
  // 指向 首个
  this.head = null;
  // 指向 末尾
  this.tail = null;

  // 新增 数据
  DoublyLinkedList.prototype.append = (element) => {
    const node = new Node(element);
    if (this.length === 0) {
      this.head = node;
      this.tail = node;
    } else {
      this.tail.next = node;
      node.prev = this.tail;
      this.tail = node;
    }
    this.length += 1;
  };

  // 特定位置插入数据
  DoublyLinkedList.prototype.insert = (position, element) => {
    if (position < 0 || position > this.length) return false;
    const node = new Node(element);
    if (this.length === 0) {
      this.head = node;
      this.tail = node;
    } else {
      if (position === 0) {
        this.head.prev = node;
        node.next = this.head;
        this.head = node;
      } else if (position === this.length) {
        this.tail.next = node;
        node.prev = this.tail;
        this.tail = node;
      } else {
        let current = this.head;
        let previous = null;
        let index = 0;
        while (index++ < position) {
          previous = current;
          current = current.next;
        }
        node.next = current;
        node.prev = previous;
        previous.next = node;
        current.prev = node;
      }
    }

    this.length += 1;
    return true;
  };

  // 获取对应位置的数据
  DoublyLinkedList.prototype.get = (position) => {
    if (position < 0 || position >= this.length) return null;
    let current = null;
    let index = null;
    if (this.length / 2 > position) {
      index = 0;
      current = this.head;
      while (index++ < position) {
        current = current.next;
      }
    } else {
      index = this.length - 1;
      current = this.tail;
      while (index-- > position) {
        current = current.prev;
      }
    }
    return current.element;
  };

  // 根据数据返回索引,若无则返回 -1
  DoublyLinkedList.prototype.indexOf = (element) => {
    let index = 0;
    let current = this.head;
    while (current) {
      if (current.element === element) {
        return index;
      }
      current = current.next;
      index++;
    }
    return -1;
  };

  // 修改某个位置的元素
  DoublyLinkedList.prototype.update = (position, element) => {
    if (position < 0 || position >= this.length) return false;
    let index = 0;
    let current = null;
    if (this.length / 2 > position) {
      current = this.head;
      while (index++ < position) {
        current = current.next;
      }
    } else {
      current = this.tail;
      index = this.length - 1;
      while (index-- > position) {
        current = current.prev;
      }
    }
    current.element = element;
  };

  // 删除特定位置的数据
  DoublyLinkedList.prototype.removeAt = (position) => {
    if (position < 0 || position >= this.length) return false;
    let current = this.head;
    if (this.length === 1) {
      this.head = null;
      this.tail = null;
    } else {
      if (position === 0) {
        this.head.next.prev = null;
        this.head = this.head.next;
      } else if (position === this.length - 1) {
        current = this.tail;
        this.tail.prev.next = null;
        this.tail = this.tail.prev;
      } else {
        let index = 0;

        while (index++ < position) {
          current = current.next;
        }
        current.prev.next = current.next;
        current.next.prev = current.prev;
      }
    }
    this.length -= 1;
    return current.element;
  };

  // 根据数据删除对应的项
  DoublyLinkedList.prototype.remove = (element) => {
    const position = this.indexOf(element);
    return this.removeAt(position);
  };

  // 打印数据
  DoublyLinkedList.prototype.toString = () => {
    return this.backwordString();
  };

  // 向后遍历
  DoublyLinkedList.prototype.backwordString = () => {
    let current = this.head;
    let resultString = "";
    while (current) {
      resultString += current.element + " ";
      current = current.next;
    }
    return resultString;
  };
  // 向前遍历
  DoublyLinkedList.prototype.forwardString = () => {
    let current = this.tail;
    let resultString = "";
    while (current) {
      resultString += current.element + " ";
      current = current.prev;
    }
    return resultString;
  };
  // 获取长度
  DoublyLinkedList.prototype.size = () => {
    return this.length;
  };
  // 判断是否为空
  DoublyLinkedList.prototype.isEmpty = () => {
    return this.length === 0;
  };
  // 获取第一个数据
  DoublyLinkedList.prototype.getHead = () => {
    return this.head.element;
  };
  // 获取最后一个数据
  DoublyLinkedList.prototype.getTail = () => {
    return this.tail.element;
  };
}

const doublyLinkedList = new DoublyLinkedList();

// 新增数据
doublyLinkedList.append("【1】我是第一条数据");
doublyLinkedList.append("【2】我是第二条数据");
doublyLinkedList.append("【3】我是第三条数据");
doublyLinkedList.insert(3, "【99】我是插入的数据");

// console.log("doublyLinkedList.get(0)", doublyLinkedList.get(0));
// doublyLinkedList.update(1, "【000】我更新咯");

// doublyLinkedList.removeAt(2);

console.log("doublyLinkedList.toString()", doublyLinkedList.toString());
doublyLinkedList.remove("【2】我是第二条数据");
console.log("doublyLinkedList.toString()", doublyLinkedList.toString());