javascript
[ JavaScript ] 数据结构与算法 —— 链表
本篇主要有三部分
- 什么是鏈表
- 鏈表的實(shí)現(xiàn)
- 鏈表的變種
源碼地址:github.com/yhtx1997/Sm…
另外,今天2019年2月18日上午發(fā)現(xiàn) 2048-vue 版,代碼版本不對(duì),且最新版本遺失,無(wú)奈只得重新修復(fù)了下
2048-vue地址: github.com/yhtx1997/Sm…
什么是鏈表
鏈表存儲(chǔ)有序的元素集合,但不同于數(shù)組,鏈表中的元素在內(nèi)存中并不是連續(xù)放置的。每個(gè) 元素由一個(gè)存儲(chǔ)元素本身的節(jié)點(diǎn)和一個(gè)指向下一個(gè)元素的引用(也稱指針或鏈接)組成。
相對(duì)于傳統(tǒng)的數(shù)組,鏈表的一個(gè)好處在于,添加或移除元素的時(shí)候不需要移動(dòng)其他元素。然 而,鏈表需要使用指針,因此實(shí)現(xiàn)鏈表時(shí)需要額外注意。數(shù)組的另一個(gè)細(xì)節(jié)是可以直接訪問(wèn)任何 位置的任何元素,而要想訪問(wèn)鏈表中間的一個(gè)元素,需要從起點(diǎn)(表頭)開(kāi)始迭代列表直到找到 所需的元素。
如下圖:
注:其中 00 06 10 12 18 為假定在內(nèi)存中的地址
我將已經(jīng)做好的鏈表存入數(shù)據(jù),然后在控制臺(tái)打印出來(lái)是這樣的:
它看起來(lái)就像是這樣的,一層套一層
其實(shí)應(yīng)該是下面這樣,類似于栓狗的鐵鏈
鏈表的實(shí)現(xiàn)
鏈表功能
- 添加元素
- 獲取指定位置元素
- 在指定位置插入元素
- 移除指定位置的元素
- 返回指定元素的位置
- 移除指定元素
- 是否為空
- 長(zhǎng)度
- 獲取表頭
- 清空鏈表
- 轉(zhuǎn)換為字符串輸出
代碼實(shí)現(xiàn)
class LinkedList {// 構(gòu)造函數(shù)聲明一些全局變量constructor(){this.count = 0; // 長(zhǎng)度this.head = undefined; // 第一個(gè)元素}// 添加元素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) { // 非空才能繼續(xù)處理// 判斷不大于最大長(zhǎng)度,不小于最小長(zhǎng)度(0)return undefined;}// 循環(huán)找到元素let current = this.head;for (let i = 0; i < index; i++){current = current.next;}return current;// 返回找到的元素}// 在指定位置插入元素insert(element, index) {// 創(chuàng)建一個(gè)元素let current = new Node(element);// 首先確定是不是在首位置插入if (index === 0){current.next = this.head;this.head = current;} else {// 找到指定位置前一個(gè)元素let previous = this.getElementAt(index - 1);// 將前一個(gè)元素的 next 賦值給插入元素的 nextcurrent.next = previous.next;// 將插入元素的 node 賦值給前一個(gè)元素的 nextprevious.next = current;}this.count++;}// 移除指定位置的元素removeAt(index) {let current = this.head;if (index === 0){this.head = current.next;} else {// 找到這個(gè)元素和這個(gè)元素之前的元素let previous = this.getElementAt(index - 1);current = previous.next;// 將這個(gè)元素的 next 賦值給這個(gè)元素之前元素的 nextprevious.next = current.next;}this.count--;// 返回要移除的元素return current.element;}// 返回指定元素的位置indexOf(element) {// 從頭開(kāi)始找let current = this.head;// 不超過(guò)最大長(zhǎng)度for (let i = 0; i < this.size() && current != null; i++){if (current.element === element){ // 找到相等的就返回下標(biāo)return i;}current = current.next;}return -1;}// 移除指定元素remove(element) {// 獲取指定元素位置let index = this.indexOf(element);// 移除指定位置元素return this.removeAt(index);}// 是否為空isEmpty() {return this.size() === 0;}// 長(zhǎng)度size() {return this.count;}// 獲取表頭getHead() {return this.head;}// 清空鏈表clear() {this.head = undefined;this.count = 0;}// 轉(zhuǎn)換為字符串輸出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); 復(fù)制代碼插入元素圖解:
現(xiàn)在有狗鏈兩節(jié),我要在中間加一節(jié)
先把兩節(jié)分開(kāi),
然后把前邊的尾部與要加的頭部相連,然后把要加的尾部與后邊的頭部相連
0 連 xx , xx 連 1
鏈表的變種
雙向鏈表
我們已經(jīng)知道鏈表的每個(gè)元素由一個(gè)存儲(chǔ)元素本身的節(jié)點(diǎn)和一個(gè)指向下一個(gè)元素的引用(也稱指針或鏈接)組成,雙向鏈表除了這個(gè)基本特性,每個(gè)元素還包含一個(gè)指向前一個(gè)元素的引用,如圖所示:
循環(huán)鏈表
循環(huán)鏈表就是鏈表的最后一個(gè)指向下一個(gè)元素的引用指向了第一個(gè)元素,使其成為循環(huán)鏈表
雙向循環(huán)鏈表
雙向循環(huán)鏈表就是雙向鏈表的第一個(gè)元素指向前一個(gè)的引用指向了最后一個(gè)元素,而最后一個(gè)元素指向下一個(gè)元素的引用指向了第一個(gè)元素,如圖所示:
總結(jié)
以上是生活随笔為你收集整理的[ JavaScript ] 数据结构与算法 —— 链表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java B2B2C源码电子商务平台
- 下一篇: Springboot集成Shiro+Re