javascript
JavaScript数据结构与算法——链表详解(上)
注:與之前JavaScript數(shù)據(jù)結(jié)構(gòu)與算法系列博客不同的是,從這篇開始,此系列博客采用es6語法編寫,這樣在學(xué)數(shù)據(jù)結(jié)構(gòu)的同時還能對ECMAScript6有進(jìn)一步的認(rèn)識,如需先了解es6語法請瀏覽http://es6.ruanyifeng.com/
1、鏈表定義
鏈表是一組節(jié)點(diǎn)組成的集合。每個節(jié)點(diǎn)都使用一個對象的引用指向它的后繼,指向另一個節(jié)點(diǎn)的引用叫做鏈。
之前我們介紹過列表,如需回顧請點(diǎn)擊這里,我們都知道列表數(shù)據(jù)結(jié)構(gòu)的底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組。在JavaScript中,數(shù)組被實(shí)現(xiàn)成了對象,相對于其他語言(比如Java)的數(shù)組相比,效率很低。鏈表相對數(shù)組而言,效率更高,能使用一維數(shù)組解決的情景鏈表幾乎都可以解決。當(dāng)然,如果需要對數(shù)據(jù)隨機(jī)訪問的話,使用數(shù)組更好。
2、鏈表實(shí)現(xiàn)解析
以上是一個鏈表,與數(shù)組不同的是,數(shù)組元素依靠它們的位置進(jìn)行引用,鏈表元素則靠相互間的關(guān)系引用。比如以上鏈表結(jié)構(gòu),我們應(yīng)該說JavaScript在Java后邊,PHP在JavaScript后邊,而不是說XXX是第幾個元素。注意:鏈表的尾元素指向NULL節(jié)點(diǎn),遍歷鏈表時,不包含頭節(jié)點(diǎn),頭節(jié)點(diǎn)只是作為鏈表的接入點(diǎn)。怎么才能遍歷完整整個鏈表?我們可以做出以下修改:
這樣就實(shí)現(xiàn)了一個有頭節(jié)點(diǎn)的鏈表。
向列表中插入一個節(jié)點(diǎn)很方便,只需要將待插入節(jié)點(diǎn)的前節(jié)點(diǎn)指向待插入節(jié)點(diǎn),同時將待插入節(jié)點(diǎn)指向指向前節(jié)點(diǎn)原本的后續(xù)節(jié)點(diǎn)即可。感覺有點(diǎn)模糊的話,看看圖就更清晰了:
理解了插入元素,從鏈表中刪除一個元素就很簡單了,只需要改變節(jié)點(diǎn)的指向即可。如圖,刪除節(jié)點(diǎn)JavaScript
3、JS實(shí)現(xiàn)鏈表數(shù)據(jù)結(jié)構(gòu)
我們將實(shí)現(xiàn)兩個類,Node類用于表示節(jié)點(diǎn),LinkedList類用于提供操作鏈表的一系列方法,比如插入、刪除節(jié)點(diǎn)等。
3.1、實(shí)現(xiàn)Node類
// Created by xiaoqiang on 23/04/2018. class Node {constructor (element) {this.element = elementthis.next = null} }解釋:element用于保存節(jié)點(diǎn)上的數(shù)據(jù),next用于保存下一個節(jié)點(diǎn)的鏈接。
3.2、實(shí)現(xiàn)LinkedList類
class LinkedList {constructor () {this.header = new Node('header') // 頭節(jié)點(diǎn)}// 查找元素find (item) {let currNode = this.headerwhile (currNode.element !== item) {currNode = currNode.next}return currNode}// 插入節(jié)點(diǎn)insert (item, newElement) {let newNode = new Node(newElement)let current = this.find(item)newNode.next = current.nextcurrent.next = newNode}// 顯示鏈表display () {let currNode = this.headerwhile(currNode.next !== null) {console.log(currNode.next.element)currNode = currNode.next}}// 查找前一個元素findPrevious (item) {let currNode = this.headerwhile (currNode.next !== null && currNode.next.element !== item) {currNode = currNode.next}return currNode}// 刪除節(jié)點(diǎn)remove (item) {let prevNode = this.findPrevious(item)if (prevNode.next !== null) {prevNode.next = prevNode.next.next}} }解釋:理解了2中的原理圖的話,應(yīng)該理解起來不是太困難,唯一注意的移除元素時,需要先知道前一個元素,這樣才能改變指向,所以需要findPrevious函數(shù)。
3.3、測試用例
let books = new LinkedList() console.log('開始插入操作') books.insert('header', 'JavaScript') books.insert('JavaScript', 'PHP') books.insert('PHP', 'Nodejs') console.log('插入后的鏈表數(shù)據(jù)為:') books.display() console.log('開始進(jìn)行移除操作') books.remove('PHP') console.log('移除后PHP后的鏈表的數(shù)據(jù)為:') books.display()3.4、完整代碼:
// Created by xiaoqiang on 23/04/2018. class Node {constructor (element) {this.element = elementthis.next = null} }class LinkedList {constructor () {this.header = new Node('header') // 頭節(jié)點(diǎn)}// 查找元素find (item) {let currNode = this.headerwhile (currNode.element !== item) {currNode = currNode.next}return currNode}// 插入節(jié)點(diǎn)insert (item, newElement) {let newNode = new Node(newElement)let current = this.find(item)newNode.next = current.nextcurrent.next = newNode}// 顯示鏈表display () {let currNode = this.headerwhile(currNode.next !== null) {console.log(currNode.next.element)currNode = currNode.next}}// 查找前一個元素findPrevious (item) {let currNode = this.headerwhile (currNode.next !== null && currNode.next.element !== item) {currNode = currNode.next}return currNode}// 刪除節(jié)點(diǎn)remove (item) {let prevNode = this.findPrevious(item)if (prevNode.next !== null) {prevNode.next = prevNode.next.next}} }let books = new LinkedList() console.log('開始插入操作') books.insert('header', 'JavaScript') books.insert('JavaScript', 'PHP') books.insert('PHP', 'Nodejs') console.log('插入后的鏈表數(shù)據(jù)為:') books.display() console.log('開始進(jìn)行移除操作') books.remove('PHP') console.log('移除后PHP后的鏈表的數(shù)據(jù)為:') books.display()3.5、運(yùn)行及結(jié)果
使用Node 運(yùn)行以上js文件,我的文件名是LinkedList.js,使用node LinkedList.js運(yùn)行結(jié)果如下:
JavaScript數(shù)據(jù)結(jié)構(gòu)與算法——鏈表詳解(上)完結(jié),有錯誤歡迎指出,晚安~
總結(jié)
以上是生活随笔為你收集整理的JavaScript数据结构与算法——链表详解(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 两个路由器如何桥接-如何接第二个路由器
- 下一篇: gradle idea java ssm