源碼地址:https://github.com/yhtx1997/S...javascript
另外,今天2019年2月18日上午發現 2048-vue 版,代碼版本不對,且最新版本遺失,無奈只得從新修復了下
2048-vue地址: https://github.com/yhtx1997/S...html
鏈表存儲有序的元素集合,但不一樣於數組,鏈表中的元素在內存中並非連續放置的。每一個
元素由一個存儲元素自己的節點和一個指向下一個元素的引用(也稱指針或連接)組成。
相對於傳統的數組,鏈表的一個好處在於,添加或移除元素的時候不須要移動其餘元素。然
而,鏈表須要使用指針,所以實現鏈表時須要額外注意。數組的另外一個細節是能夠直接訪問任何
位置的任何元素,而要想訪問鏈表中間的一個元素,須要從起點(表頭)開始迭代列表直到找到
所需的元素。
以下圖:
注:其中 00 06 10 12 18 爲假定在內存中的地址vue
我將已經作好的鏈表存入數據,而後在控制檯打印出來是這樣的:java
它看起來就像是這樣的,一層套一層node
其實應該是下面這樣,相似於栓狗的鐵鏈git
// 鏈表元素 class Node { constructor(element) { this.element = element; // 元素 this.next = undefined; // 指向下一個元素 } } class LinkedList { // 構造函數聲明一些全局變量 constructor(){ this.count = 0; // 長度 this.head = undefined; // 第一個元素 } // 添加元素 push(element) { } // 獲取指定位置元素 getElementAt(index) { } // 在指定位置插入元素 insert(element, index) { } // 移除指定位置的元素 removeAt(index) { } // 返回指定元素的位置 indexOf(element) { } // 移除指定元素 remove(element) { } // 是否爲空 isEmpty() { } // 長度 size() { } // 獲取表頭 getHead() { } // 清空鏈表 clear() { } // 轉換爲字符串輸出 toString() { } }
class LinkedList { // 構造函數聲明一些全局變量 constructor(){ this.count = 0; // 長度 this.head = undefined; // 第一個元素 } // 添加元素 push(element) { const node = new Node(element); if (this.head === undefined) { this.head = node; } else { let current = this.head; while (current.next !== undefined) { current = current.next; } current.next = node; } this.count++; } // 獲取指定位置元素 getElementAt(index) { // 判斷不是空鏈表 if (this.isEmpty() || index > this.count || index < 0) { // 非空才能繼續處理 // 判斷不大於最大長度,不小於最小長度(0) return undefined; } // 循環找到元素 let current = this.head; for (let i = 0; i < index; i++){ current = current.next; } return current;// 返回找到的元素 } // 在指定位置插入元素 insert(element, index) { // 建立一個元素 let current = new Node(element); // 首先肯定是否是在首位置插入 if (index === 0){ current.next = this.head; this.head = current; } else { // 找到指定位置前一個元素 let previous = this.getElementAt(index - 1); // 將前一個元素的 next 賦值給插入元素的 next current.next = previous.next; // 將插入元素的 node 賦值給前一個元素的 next previous.next = current; } this.count++; } // 移除指定位置的元素 removeAt(index) { let current = this.head; if (index === 0){ this.head = current.next; } else { // 找到這個元素和這個元素以前的元素 let previous = this.getElementAt(index - 1); current = previous.next; // 將這個元素的 next 賦值給這個元素以前元素的 next previous.next = current.next; } this.count--; // 返回要移除的元素 return current.element; } // 返回指定元素的位置 indexOf(element) { // 從頭開始找 let current = this.head; // 不超過最大長度 for (let i = 0; i < this.size() && current != null; i++){ if (current.element === element){ // 找到相等的就返回下標 return i; } current = current.next; } return -1; } // 移除指定元素 remove(element) { // 獲取指定元素位置 let index = this.indexOf(element); // 移除指定位置元素 return this.removeAt(index); } // 是否爲空 isEmpty() { return this.size() === 0; } // 長度 size() { return this.count; } // 獲取表頭 getHead() { return this.head; } // 清空鏈表 clear() { this.head = undefined; this.count = 0; } // 轉換爲字符串輸出 toString() { if (this.head == null) { return ''; } let objString = `${this.head.element}`; let current = this.head.next; for (let i = 1; i < this.size() && current != null; i++) { objString = `${objString},${current.element}`; current = current.next; } return objString; } } let a = new LinkedList(); a.push('a'); a.push('b'); a.push('c'); a.push('d'); a.push('e'); a.push('f'); a.push('h'); a.push('i'); a.push('j'); a.push('k'); a.push('l'); a.push('m'); a.push('n'); a.push('o'); a.push('p'); a.push('q'); a.remove('a'); a.insert('a',1); console.log(a);
插入元素圖解:github
如今有狗鏈兩節,我要在中間加一節數組
先把兩節分開,函數
而後把前邊的尾部與要加的頭部相連,而後把要加的尾部與後邊的頭部相連 this
0 連 xx , xx 連 1
咱們已經知道鏈表的每一個元素由一個存儲元素自己的節點和一個指向下一個元素的引用(也稱指針或連接)組成,雙向鏈表除了這個基本特性,每一個元素還包含一個指向前一個元素的引用,如圖所示:
循環鏈表就是鏈表的最後一個指向下一個元素的引用指向了第一個元素,使其成爲循環鏈表
雙向循環鏈表就是雙向鏈表的第一個元素指向前一個的引用指向了最後一個元素,而最後一個元素指向下一個元素的引用指向了第一個元素,如圖所示: