原文:
概念:
鏈表存儲有序的元素集合,但不同於數組,鏈表中的元素在內存中並不是連續放置的。每個 元素由一個存儲元素本身的節點和一個指向下一個元素的引用(也稱指針或鏈接)組成。下圖展示了鏈表的結構:
相對於傳統的數組,鏈表的一個好處在於,添加或移除元素的時候不需要移動其他元素。然而,鏈表需要使用指針,因此實現鏈表時需要額外注意。 數組的另一個細節是可以直接訪問任何位置的任何元素,而要想訪問鏈表中間的一個元素,需要從起點(表頭)開始迭代列表直到找到所需的元素。
普通鏈表:
// 鏈表節點 class Node { constructor(element) { this.element = element; this.next = null; } } // 鏈表 class LinkedList { constructor() { this.head = null; this.length = 0; // length 同數組 length 與下標關系 } // 追加元素 append(element) { let node = new Node(element); let current = null; // 指針? if (this.head === null) { this.head = node; } else { current = this.head; while (current.next) { current = current.next; } current.next = node; } this.length++; } // 任意位置插入元素 insert (position, element) { if (position >= 0 && position <= this.length) { let node = new Node(element); let current = this.head; let previous = null; let index = 0; if (position === 0) { this.head = node; } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } this.length++; return true } return false } // 移除指定位置元素 removeAt(position) { if (position > -1 && position < length) { let current = this.head; let previous = null; let index = 0; if (position === 0) { this.head = current.next; } else { while(index++ < position) { previous = current; current = current.next; } previous.next = current.next; } this.length--; return current.element; } return null } // 尋找元素下標 findIndex(element) { let current = this.head; let index = -1; while (current) { if (element === current.element) { return index + 1; } index++; current = current.next; } return -1; } // 刪除指定文檔 remove(element) { let index = this.findIndex(element); return removeAt(index); } isEmpty() { return !this.length; } size() { return this.length; } // 輸出字符串 toString() { let current = this.head; let string = ''; while (current) { string += ` ${current.element}`; current = current.next; } return string; } } var ll = new LinkedList(); console.log(ll); ll.append(2); ll.append(6); ll.append(24); ll.append(152); ll.insert(3, 18); console.log(ll); console.log(ll.findIndex(24));
雙向鏈表:
class Node { constructor(element) { this.element = element; this.prev = null; this.next = null; } } // 雙向鏈表 class DoubleLinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } // 任意位置插入元素 insert(position, element) { if (position >= 0 && position <= ehis.length) { let node = new Node(element); let current = this.head; let previous = null; this.index = 0; // 首位 if (position === 0) { if (!head) { this.head = node; this.tail = node; } else { node.next = current; this.head = node; current.prev = node; } } else if (position === this.length) { // 末尾 current = this.tail; current.next = node; node.prev = current; this.tail = node; } else { // 中間 while(index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; current.prev = node; node.prev = previous; } this.length++; return true; } return false; } // 移除指定位置元素 removeAt(position) { if (position > -1 && position < this.length) { let current = this.head; let previous = null; let index = 0; // 首位 if (position === 0) { this.head = this.head.next this.head.prev = null if (this.length === 1) { this.tail = null } } else if (position === this.length - 1) { // 末位 this.tail = this.tail.prev this.tail.next = null } else { // 中位 while (index++ < position) { previous = current current = current.next } previous.next = current.next current.next.prev = previous } this.length--; return current.element; } else { return null; } } // 其他方法 }
循環鏈表:
具體代碼實現就不寫了,下圖是示意圖