摘要:實(shí)現(xiàn)移除給定的元素要移除的元素返回值表示移除成功方法說(shuō)明移除單向鏈表中某個(gè)位置的元素。的前端樂(lè)園原文鏈接寒假前端學(xué)習(xí)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法二鏈表
鏈表簡(jiǎn)介本系列的第一篇文章: 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一),棧與隊(duì)列
第二篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(二):鏈表
第三篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(三):集合
第四篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(四):二叉搜索樹(shù)
鏈表是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),也屬于線性表,但不會(huì)按線性的順序來(lái)儲(chǔ)存數(shù)據(jù)。而是在每一個(gè)節(jié)點(diǎn)中,儲(chǔ)存了下一個(gè)節(jié)點(diǎn)的指針??梢钥磮D理解。(有C語(yǔ)言基礎(chǔ)的可能比較好理解)。
使用鏈表結(jié)構(gòu)可以克服數(shù)組需要預(yù)先知道數(shù)據(jù)大小的缺點(diǎn)(C語(yǔ)言的數(shù)組需要預(yù)先定義長(zhǎng)度),鏈表結(jié)構(gòu)可以充分利用計(jì)算機(jī)內(nèi)存空間,實(shí)現(xiàn)靈活的內(nèi)存動(dòng)態(tài)管理。
接下來(lái)就是介紹兩種常見(jiàn)的鏈表: 單向鏈表,雙向鏈表在JavaScript中的實(shí)現(xiàn)。
單向鏈表鏈表中最簡(jiǎn)單的形式就是單向鏈表,鏈表中的節(jié)點(diǎn)都包含兩個(gè)部分,第一部分儲(chǔ)存著自身信息,第二部分則儲(chǔ)存有指向下一節(jié)點(diǎn)的指針。最后一個(gè)節(jié)點(diǎn)則指向NULL,如圖所示:
首先,創(chuàng)建一個(gè)構(gòu)造函數(shù)。
/** * 單向鏈表構(gòu)造函數(shù) */ function LinkedList() { /** * 單向鏈表中節(jié)點(diǎn)的構(gòu)造函數(shù) * @param {Any} element 要傳入鏈表的節(jié)點(diǎn) */ var Node = function(element) { this.element = element; //下個(gè)節(jié)點(diǎn)的地址 this.next = null; } //單向鏈表的長(zhǎng)度 var length = 0; //單向鏈表的頭結(jié)點(diǎn),初始化為NULL var head = null; }
不難看出,單向鏈表構(gòu)造函數(shù)比棧與隊(duì)列要復(fù)雜許多。
單向鏈表需要有如下的方法:
append(element): 添加元素到鏈表尾部
insert(position,element): 向單向鏈表中某個(gè)位置插入元素
indexOf(element): 尋找某個(gè)元素在單向鏈表中的位置
remove(element): 移除給定的元素
removeAt(position): 移除單向鏈表中某個(gè)位置的元素
getHead(): 獲取單向鏈表的頭部
isAmpty(): 檢查單向鏈表是否為空,為空則返回true
toString(): 將鏈表所有內(nèi)容以字符串輸出
size(): 返回單向鏈表長(zhǎng)度
append方法:說(shuō)明: 向單向鏈表尾部添加元素。
實(shí)現(xiàn):
/** * 向單向鏈表尾部添加元素 * @param {Any} element 要加入鏈表的節(jié)點(diǎn) */ this.append = function(element) { var node = new Node(element); var current; if (head == null) { head = node; } else { // 當(dāng)前項(xiàng)等于鏈表頭部元素. // while循環(huán)到最后一個(gè),從而將該節(jié)點(diǎn)加入鏈表尾部。 current = head; // 當(dāng)next為null時(shí),判定為false。退出循環(huán)。 while (current.next) { current = current.next; } current.next = node; } length++; };insert方法:
說(shuō)明: 向單向鏈表中某個(gè)位置插入元素。
實(shí)現(xiàn):
/** * 向單向鏈表中插入某個(gè)元素 * @param {Number} position 要插入的位置 * @param {Any} element 要插入的元素 * @return {Boolean} 插入成功返回true,失敗返回false */ this.insert = function(position, element) { if (position >= 0 && position <= length) { var node = new Node(element); var current = head; var previous; var index = 0; if (position == 0) { node.next = current; head = node; } else { while (index++ < position) { previous = current; current = current.next; } previous.next = node; node.next = current; } length++; return true; } else { return false; } };indexOf方法:
說(shuō)明:尋找某個(gè)元素在單向鏈表中的位置。
實(shí)現(xiàn):
/** * 尋找某個(gè)元素在單向鏈表中的位置 * @param {Any} element 要尋找的元素 * @return {Number} 返回值>=0則代表找到相應(yīng)位置 */ this.indexOf = function(element) { var current = head; var index = -1; while (current) { if (element === current.element) { return index; } index++; current = current.next; } return -1; };remove方法:
說(shuō)明: 移除給定的元素。
實(shí)現(xiàn):
/** * 移除給定的元素 * @param {Any} element 要移除的元素 * @return {Number} 返回值>=0表示移除成功 */ this.remove = function(element) { var index = this.indexOf(element); return this.removeAt(index); };removeAt方法:
說(shuō)明:移除單向鏈表中某個(gè)位置的元素。
實(shí)現(xiàn):
/** * 移除單向鏈表中某一個(gè)元素 * @param {Number} position 要移除元素的位置 * @return {Any} 移除成功返回被移除的元素,不成功則返回NULL */ this.removeAt = function(position) { if (position > -1 && position < length) { var current = head; var previous; var index = 0; if (position == 0) { // 因?yàn)橹癶ead指向第一個(gè)元素,現(xiàn)在把head修改為指向第二個(gè)元素。 // 核心概念在于鏈表前后全靠指針鏈接,而非數(shù)組一般。 // 所以只需要改變head的元素。 head = current.next; } else { while (index++ < position) { // previous指要操作元素位置之前的那個(gè)元素,current表示之后的那個(gè)元素。 previous = current; current = current.next; } previous.next = current.next; } length--; return current.element; } else { return null; } };getHead方法:
說(shuō)明:獲取單向鏈表的頭部。
實(shí)現(xiàn):
/** * 獲取單向鏈表的頭部 * @return {Any} 單向鏈表的頭部 */ this.getHead = function() { return head; }isAmpty、toString、size方法
實(shí)現(xiàn):
/** * 判斷單向鏈表是否為空 * @return {Boolean} 為空則返回true,不為空則返回false */ this.isAmpty = function() { return length === 0 }; /** * 將鏈表所有內(nèi)容以字符串輸出 * @return {String} 要輸出的字符串 */ this.toString = function() { var current = head; var string = ""; while (current) { string += current.element; current = current.next; } return string; }; /** * 返回單向鏈表長(zhǎng)度 * @return {Number} 單向鏈表的長(zhǎng)度 */ this.size = function() { return length; };源代碼
以上的就是單向鏈表在JavaScript中的實(shí)現(xiàn),有興趣的同學(xué)可以自己下載源代碼查看。
雙向鏈表單向鏈表-源代碼
雙向鏈表與單向鏈表很是相像。在單向鏈表中,只有指向下一個(gè)節(jié)點(diǎn)的鏈接。但在雙向鏈表中,還有指向上一個(gè)節(jié)點(diǎn)的鏈接,是雙向的。
如圖所示:
首先,依然是構(gòu)造函數(shù):
/** * 雙向鏈表的構(gòu)造函數(shù) */ function DoublyLinkedList() { /** * 雙向鏈表中節(jié)點(diǎn)的構(gòu)造函數(shù) * @param {Any} element 要傳入鏈表的元素 */ var Node = function(element) { this.element = element; this.prev = null; this.next = null; } //雙向鏈表的長(zhǎng)度 var length = 0; //雙向鏈表的頭結(jié)點(diǎn),初始化為NULL var head = null; //雙向鏈表的尾結(jié)點(diǎn),初始化為NULL var tail = null; }
雙向鏈表需要有如下的方法:
append(element): 添加元素到雙向鏈表尾部
insert(position,element): 向雙向鏈表中某個(gè)位置插入元素
removeAt(position): 移除雙向鏈表中某個(gè)位置的元素
showHead(): 獲取雙向鏈表的頭部
showLength(): 獲取雙向鏈表長(zhǎng)度
showTail(): 獲取雙向鏈表尾部
append方法:說(shuō)明: 添加元素到雙向鏈表尾部
實(shí)現(xiàn):
/** * 向鏈表尾部添加元素 * @param {Any} element 要加入鏈表的節(jié)點(diǎn) * @return {Any} 加入鏈表的節(jié)點(diǎn) */ this.append = function(element) { var node = new Node(element); if (head === null) { head = node; tail = node; } else { var previous; var current = head; while (current.next) { current = current.next; } current.next = node; node.prev = current; tail = node; } length++; return node; };insert方法:
說(shuō)明: 向雙向鏈表中某個(gè)位置插入元素。
實(shí)現(xiàn):
/** * 向鏈表中插入某個(gè)元素 * @param {Number} position 要插入的位置 * @return {Boolean} 插入成功返回true,失敗返回false */ this.insert = function(position, element) { if (position >= 0 && position <= length) { var node = new Node(element); var index = 0; var previous; var current = head; if (position === 0) { if (head === null) { head = node; tail = node; } else { current.prev = node; node.next = current; head = node; } } else if (position === length) { current = tail; current.next = node; node.prev = current; tail = node; } else { while (index++ < position) { previous = current; current = current.next; } previous.next = node; node.prev = previous; current.prev = node; node.next = current; } length++; return true; } else { return false; } };removeAt方法:
說(shuō)明:移除雙向鏈表中某個(gè)位置的元素。
實(shí)現(xiàn):
/** * 移除鏈表中某一個(gè)元素 * @param {Number} position 要移除元素的位置 * @return {Any} 移除成功返回被移除的元素,不成功則返回false */ this.removeAt = function(position) { if (position > -1 && position < length) { var current = head; var index = 0; var previous; if (position === 0) { head = current.next; if (length === 1) { tail = null; head.prev = null; } } else if (position === length - 1) { current = tail; tail = current.prev; tail.next = null; } else { while (index++ < position) { previous = current.prev; current = current.next; } previous.next = current.next; current.next.prev = previous; } length--; return current.element; } else { return false; } };showHead、showLength、showTail方法
實(shí)現(xiàn):
/** * 獲取鏈表的頭部 * @return {Any} 鏈表的頭部 */ this.showHead = function() { return head; }; /** * 獲取鏈表長(zhǎng)度 * @return {Number} 鏈表長(zhǎng)度 */ this.showLength = function() { return length; }; /** * 獲取鏈表尾部 * @return {Any} 鏈表尾部 */ this.showTail = function() { return tail; };源代碼
源代碼在此~
感想雙向鏈表-源代碼
鏈表這一節(jié),基本全部都是先按需求寫(xiě)代碼,寫(xiě)完后再和書(shū)上對(duì)比。發(fā)現(xiàn)簡(jiǎn)直被瞬間秒成渣。自己寫(xiě)的很多暗坑,邏輯也很混亂??磥?lái)還是太年輕了。
有興趣的同學(xué),也可以自己試試只看要求先寫(xiě)代碼,寫(xiě)完后再與書(shū)上比對(duì),就知道自己的不足了。
前端路漫漫,且行且歌~
最后附上本人博客地址和原文鏈接,希望能與各位多多交流。
Lxxyx的前端樂(lè)園
原文鏈接:寒假前端學(xué)習(xí)(4)——學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(二):鏈表
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/91599.html
摘要:技巧使你的更加專(zhuān)業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來(lái)吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專(zhuān)業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專(zhuān)業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...
摘要:技巧使你的更加專(zhuān)業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來(lái)吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專(zhuān)業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專(zhuān)業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...
摘要:筆者作為一位,將工作以來(lái)用到的各種優(yōu)秀資料神器及框架整理在此,畢竟好記性不如爛鍵盤(pán),此前端知識(shí)點(diǎn)大百科全書(shū)前端掘金,,不定期更新技巧前端掘金技巧,偶爾更新。計(jì)算數(shù)組的極值技巧使你的更加專(zhuān)業(yè)前端掘金一個(gè)幫你提升技巧的收藏集。 CSS 樣式畫(huà)各種圖形 - 前端 - 掘金下面是一些我在 CSS 中經(jīng)常用到的圖案,還有一些是在css-tricks看到的。記錄一下,以后會(huì)用到。會(huì)持續(xù)更新… 一、...
摘要:筆者作為一位,將工作以來(lái)用到的各種優(yōu)秀資料神器及框架整理在此,畢竟好記性不如爛鍵盤(pán),此前端知識(shí)點(diǎn)大百科全書(shū)前端掘金,,不定期更新技巧前端掘金技巧,偶爾更新。計(jì)算數(shù)組的極值技巧使你的更加專(zhuān)業(yè)前端掘金一個(gè)幫你提升技巧的收藏集。 CSS 樣式畫(huà)各種圖形 - 前端 - 掘金下面是一些我在 CSS 中經(jīng)常用到的圖案,還有一些是在css-tricks看到的。記錄一下,以后會(huì)用到。會(huì)持續(xù)更新… 一、...
摘要:本系列所有文章第一篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊(duì)列第二篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之鏈表第三篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之集合第四篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之字典和散列表第五篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之二叉搜索樹(shù)簡(jiǎn)單介紹鏈表鏈表一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),可 本系列所有文章:第一篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊(duì)列第二篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之鏈表第三篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之集合第四篇文章:學(xué)習(xí)數(shù)...
閱讀 1456·2021-11-11 16:54
閱讀 2534·2021-09-22 10:51
閱讀 2720·2019-08-30 15:44
閱讀 3277·2019-08-29 17:05
閱讀 1538·2019-08-29 17:01
閱讀 3003·2019-08-29 12:28
閱讀 2557·2019-08-26 13:50
閱讀 1811·2019-08-23 16:47