JavaScript实现链表增删改查逆序等功能

9 阅读2分钟

本文主要写了对于链表的操作,功能:链表添加到最后,指定位置和元素内容添加,根据位置删除,根据元素内容删除,链表长度、是否为空、获取第一个节点、获取链表字符串内容、根据元素获取位置。

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

function defaultEquals(a, b) {
  return a === b;
}

class LinkedList {
  constructor(equalsFn = defaultEquals) {
    this.head = undefined; // 保持第一个元素的饮用
    this.count = 0; // 存储链表的元素数量
    this.equalsFn = equalsFn; // 比较两个节点的元素是否相同
  }
  push(element) {
    const node = new Node(element); // 创建一个节点
    let current;
    if (this.head == null) {
      // undefined == null 为 true
      // 此时链表上没有任何元素,只需要在第一个节点添加即可
      // node 节点的next 默认是 null 所以,链表的next 也是null
      this.head = node;
    } else {
      // 只能找到第一个节点元素的引用,因此需要从第一个节点开始循环
      current = this.head;
      // 找到链表中的最后一个节点
      while (current.next != null) {
        current = current.next;
      }
      current.next = node;
    }
    this.count++;
  }
  // 插入元素到指定位置
  insert(element, index) {
    if (index > 0 && index <= this.count) {
      const node = new Node(element);
      if (index === 0) {
        let current = this.head;
        node.next = current;
        this.head = node;
      } else {
        const previous = this.getElementAt(index - 1);
        node.next = previous.next;
        previous.next = node;
      }
      this.count++;
      return true;
    }
    return false;
  }
  // 根据输入循环链表
  getElementAt(index) {
    if (index >= 0 && index <= this.count) {
      let node = this.head;
      for (let i = 0; i < index && node != null; i++) {
        node = node.next;
      }
      return node;
    }
    return undefined;
  }
  // 删除特定位置的节点
  removeAt(index) {
    // 验证传入的节点位置是否有效
    if (index >= 0 && index < this.count) {
      let current = this.head;
      if (index === 0) {
        this.head = current.next; // 更改首元素节点
      } else {
        const previous = this.getElementAt(index - 1);
        current = previous.next;

        // for (let i = 0; i < index; i++) {
        //   // 因为每次循环 都会将 current.next 的值赋给 current,所以节点循环是通过 current 进行
        //   previous = current; //
        //   current = current.next;
        // }
        // // 删除 index 位置上的 元素节点,只需要改变要删除节点的引用,就可以将这个节点从链表中删除。
        // // previous 要删除的节点的前一个节点
        // /*
        // 节点位置:0 1 2 3 4
        // 节点元素:1 2 3 4 5
        //   删除输入的是 3
        //   上面循环:
        //   0 1 2
        //   1 2 3
        //   previous 的节点内容是 3
        // */
        previous.next = current.next;
      }
      this.count--;
      return current.element;
    }
    return undefined;
  }
  // 根据元素删除节点
  remove(element) {
    const index = this.indexOf(element);
    return this.removeAt(index);
  }
  // 根据节点内容查找所在的位置
  indexOf(element) {
    let current = this.head;
    for (let i = 0; i < this.count && current != null; i++) {
      if (this.equalsFn(element, current.element)) {
        return i;
      }
      current = current.next;
    }
    return -1;
  }
  size() {
    return this.count;
  }
  isEmpty() {
    return this.size() === 0;
  }
  getHead() {
    return this.head;
  }
  toString() {
    if (this.count > 0) {
      let objString = '';
      let current = this.head;
      for (let i = 0; i < this.count && current != null; i++) {
        objString = `${objString} ${i}-${current.element}`;
        current = current.next;
      }
      return objString;
    }
  }
// 链表逆序
reverse() {
let current = this.head;
let prev = null;
while (current) {
  const nextTemp = current.next;
  current.next = prev;
  prev = current;
  current = nextTemp;
}
this.head = prev; // 算法题不用写这一行
return prev;
}
}