常用数据结构之链表

193 阅读1分钟

链表的特点

  • 中链表由节点组成,一个节点包含一份储存的数据和一个指针,指针指向下一个节点或 null
  • 链表在内存中不是连续的,数组是连续的
  • 增加和删除数据的效率高,数组增加和删除数据的效率低
  • 但是查找数据效率低,只能通过循环遍历,数组查找效率很高因为是连续的可以直接通过索引查找
  • 链表方便拓展,定义时不需要需要指定大小,数组不利于拓展要指定大小

链表的实现

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

const head = Symbol('head');

class LinkedList {
  constructor() {
    this[head] = null;
  }
// 在尾部增加节点
  addLast(data) {
    const newNode = new LinkedListNode(data);
    if (this[head] === null) {
      this[head] = newNode;
    } else {
      let current = this[head];
      while (current.next !== null) {
        current = current.next;
      }
      current.next = newNode;
    }
  }

// 在某节点前增加数据
  insertBefore(data, index) {
    const newNode = new LinkedListNode(data);
    if (this[head] === null) {
      throw RangeError(`Index ${index} does not exist in the list.`);
    }
    if (index === 0) {
      newNode.next = this[head];
      this[head] = newNode;
    } else {
      let current = this[head];
      let previous = null;
      let i = 0;
      while (i < index && current.next !== null) {
        previous = current;
        current = current.next;
        i++;
      }
      if (i < index) {
        throw RangeError(`Index ${index} does not exist in the list.`);
      }

      previous.next = newNode;
      newNode.next = current;
    }
  }
  
// 在某节点后增加数据
  insertAfter(data, index) {
    const newNode = new LinkedListNode(data);
    if (this[head] === null) {
      throw RangeError(`Index ${index} does not exist in the list.`);
    }
    let i = 0;
    let current = this[head];
    while (i < index && current.next !== null) {
      current = current.next;
      i++;
    }
    if (i < index) {
      throw RangeError(`Index ${index} does not exist in the list.`);
    }
    newNode.next = current.next;
    current.next = newNode;
  }

// 查找数据
  get(index) {
    if (index > -1) {
      let current = this[head];
      while (current !== null && index > 0) {
        current = current.next;
        index -= 1;
      }
      return current !== null ? current.data : undefined;
    } else {
      return undefined;
    }
  }

// 删除某数据
  remove(index) {
    if (this[head] === null || index < 0) {
      throw new RangeError(`Index ${index} does not exist in the list.`);
    }

    let current = this[head];
    let previous = null;
    let i = 0;

    if (index === 0) {
      this[head] = current.next;
      current.next = null;
      return current.data;
    }

    while (current !== null && i < index) {
      previous = current;
      current = current.next;
      i++;
    }

    if (current !== null) {
      previous.next = current.next;
      current.next = null;
      return current.data;
    }
    throw new RangeError(`Index ${index} does not exist in the list.`);
  }
}

常见题目:反转链表

反转整个链表

function reverse(a) {
  let pre = null;
  let cur = a;
  let nxt = a;
  while (cur != null) {
    nxt = cur.next;
    cur.next = pre;
    pre = cur;
    cur = nxt;
  }
  return pre;
}

反转部分链表

function reverseGroup(a, b) {
  let pre = null;
  let cur = a;
  let nxt = a;
  while (cur != b) {
    nxt = cur.next;
    cur.next = pre;
    pre = cur;
    cur = nxt;
  }
  return pre;
}