在儲存多個元素時,我們最常用的資料結構可能是陣列,究其原因可能是陣列訪問方便,可以直接通過訪問,但是陣列也存在一定的缺點,陣列的大小是固定,陣列在執行插入或者刪除的時候成本很高。
鍊錶儲存的是有序的元素集合,和陣列不同的是,鍊錶中的元素在記憶體並不是連續放置,每個元素由乙個儲存元素本身的節點和乙個指向下乙個元素的引用組成,結構如下圖所示:
和陣列相比,鍊錶的優勢在於:新增或者刪除元素不需要移動其他元素,劣勢在與鍊錶相對於陣列結構更複雜,需要乙個指向下乙個元素的指標,在訪問鍊錶中的某個元素也需要從頭迭代,而不是像陣列一樣直接訪問
首先讓我們來看一下鍊錶的大概骨架,需要定義一些什麼屬性:
function
linkedlist()
let length = 0
let head = null
} this.insert = function (position, element)
this.removeat = function (position)
this.remove = function (element)
this.indexof = function (element)
this.isempty = function ()
this.size = function ()
this.gethead = function ()
this.tostring = function ()
this.print = function ()
}複製**
首先linkedlist裡面需要定義乙個node輔助類,表示要加入鍊錶的項,包含乙個element屬性和乙個指向下乙個節點的指標next,接下來定義了乙個指標的頭head和指標的長度length,然後就是最重要的類裡面的方法,接下來就讓我們一起來看這些方法的職責和實現
鍊錶在向尾部追加元素的時候有兩種情況:鍊錶為空,新增的是第乙個元素,或者鍊錶不為空,追加元素,下面來看具體實現:
let node = new node(element), current
if (head === null) else
current.next = node // 找到最後一項,將新增元素連線
}length++
}複製**
現在讓我們先來看第乙個種情況,鍊錶為空時,插入就直接是頭,因此直接將node賦值給head就行,第二種情況,當鍊表有元素時,就需要先迴圈鍊錶,找到最後一項,然後將最後一項的next指標指向node
現在讓我們來看看怎麼從指定位置移除元素,移除元素也有兩個場景,第一種是移除第乙個元素,第二種是移除第乙個以外的任意乙個元素,來看具體實現:
this.removeat = function (position) else
previous.next = current.next
}length--
return
current.element
} else
}複製**
接下來一起來分析一下上面的**,首先判斷要刪除的位置是不是有效的位置,然後來看第一種情況,當移除的元素是第一項是時,此時直接將head指向第二個元素就行了,第二種情況就會稍微複雜一點,首先需要乙個index控制遞增,previous記錄前乙個位置,移除當前元素,就是將前乙個元素的next指向下乙個元素,來看乙個示意圖:
因此在while迴圈中始終用previous記錄上乙個位置元素,current記錄下乙個元素,跳出迴圈時,上乙個元素的next指標指向當前元素的next指標指向的元素,就將當前元素移出鍊錶
接下來來看在任意位置插入的insert方法,這個方法同樣需要考慮兩種情況,插入位置在頭部和插入位置不在頭部,下面來看一下具體實現:
this.insert = function (position, element) else
previous.next = node
node.next = current
}length++
return
true
} else
}複製**
先來看第一種情況,鍊錶起點新增乙個元素,將node.next指向current,然後再將node的引用賦值給head,這樣就再鍊錶的起點新增了乙個元素,第二種情況,在其他位置插入乙個元素,previous是插入元素的前乙個元素,current為插入元素的後乙個元素,想要插入乙個元素,就需要將前乙個元素的next指向要插入的元素,要插入元素的next指向下乙個元素,來看示意圖:
如上圖所示:將新項node插入到previous和current之間,需要將previous.next指向node,node.next指向current,這樣就在鍊錶中插入了乙個新的項
tostring方法會把linkedlist物件轉換成乙個字串,下面來看具體實現:
this.tostring = function ()
return string
}複製**
迴圈遍歷所有元素,以head為起點,當存在下乙個元素時,就將其拼接到字串中,直到next為null
indexof方法返回對應元素的位置,存在就返回對應的索引,不存在返回-1,來看具體的實現:
this.indexof = function (element)
index++
current = current.next
}return
-1 }
複製**
遍歷鍊錶,當前元素的值與目標值一致時返回元素的位置index,遍歷完鍊錶還沒找到則返回-1
由於這幾個方法實現比較簡單,直接來看具體實現:
this.remove = function (element)
this.isempty = function ()
this.size = function ()
this.gethead = function ()
複製**
JS資料結構學習 鍊錶
在儲存多個元素時,我們最常用的資料結構可能是陣列,究其原因可能是陣列訪問方便,可以直接通過訪問,但是陣列也存在一定的缺點,陣列的大小是固定,陣列在執行插入或者刪除的時候成本很高。鍊錶儲存的是有序的元素集合,和陣列不同的是,鍊錶中的元素在記憶體並不是連續放置,每個元素由乙個儲存元素本身的節點和乙個指向...
資料結構學習 鍊錶
將從下面4部分進行介紹 首先介紹鍊錶是什麼,然後介紹為什麼定義鍊錶,接著是鍊錶的分類,最後簡單介紹一下鍊錶結點的插入與刪除方法。首先,在介紹鍊錶之前,我們先介紹一下什麼是順序儲存結構。我們知道資料在計算機中的儲存就像貨物在倉庫中的儲存一樣,不但占用一定的空間,還要有乙個標示儲存位置的位址。計算機通過...
資料結構學習 鍊錶
由於不必須按順序儲存,鍊錶在插入的時候可以達到o 1 的複雜度,比另一種線性表順序表快得多,但是查詢乙個節點或者訪問特定編號的節點則需要o n 的時間,而線性表和順序表相應的時間複雜度分別是o logn 和o 1 使用鍊錶結構可以克服陣列鍊錶需要預先知道資料大小的缺點,鍊錶結構可以充分利用計算機記憶...