鍊錶也是乙個非常基本的資料結構,跟陣列有很大的不同。
我們知道陣列是占用連續記憶體的線性結構
add就是該陣列的首位址,訪問元素可以使用add【下標】。然而我們可以發現陣列占用連續的空間,需要擴容的時候需要開闢更大的連續空間然後複製過去,並且當我們移除 插入元素時,需要遍歷陣列將元素進行前移補位和後移空位。陣列雖然訪問方便,但是對於這樣的操作是在是太不友好了。
(注意術語)鍊錶的元素稱為節點,第乙個是頭結點,最後乙個是尾節點,指向後面的指標是後向指標。跟陣列的方式相比,儲存相同的元素值時的樣子大概是這樣:
對於鍊錶來說,我們僅需要改變兩個元素的內容就可以。我們開闢新的元素空間並賦值為55(注意,前面說過,鍊錶本來也不是線性的,每個元素的位置是隨機申請的),將元素0的後向指標指向新的元素,並將新的元素的後向指標指向原本的1號元素,這就完美的將乙個新的元素插入了進來。
但是對於陣列就不這麼容易了,我們需要將1號元素和之後的所有元素後移一位,並且實際操作中有可能觸發擴容操作。當陣列的長度非常大的時候,鍊錶插入和刪除操作的優勢就越發的明顯了。不是很確切的來說,鍊錶是犧牲了記憶體空間和順序訪問的效能換來了這個優勢。
有的人可能會問,鍊錶只能從前往後訪問嗎...大佬們當然考慮過這個問題,為此就出現了雙向鍊錶。同樣的原理,雙向鍊錶只是多了乙個前向指標,使得可以訪問上乙個元素
雙向鍊錶的優勢顯而易見。在插入好刪除元素的時候,我們需要更改的指標多了兩個。
前乙個元素的後向指標和後乙個元素的前向指標都需要指向新的元素,並且新的元素也是有前向指標和後向指標兩個指標。對於學習鍊錶,只要前後指標的關係弄明白,就一點都不亂了。如何弄明白??自己畫兩次插入和刪除操作的示意圖就明白了,有時候光看是不行的。
對於單向鍊錶和雙向鍊錶都是有元素間關係的指標,我們遍歷鍊錶需要借助指標得到下乙個元素。
單向鍊錶
大概的操作時
首先頭結點的位址是已知的,這是就是head吧 節點的值為value 前向指標為pre 後向指著為next
臨時值=head.next # 獲取頭結點的後向指標
# 如果指標空 則表示沒有下乙個元素
while 臨時值不為空: # 後向指標不為空表示有元素
輸出(臨時值.value)
臨時值 = 臨時值.next # 獲取當前節點的後向指標
鍊錶的操作精髓就是指標,元素由指標關聯在一起,形成乙個完整的鏈條。
最後再重新思考一下,跟陣列相比鍊錶的優勢是什麼?? 它的精髓又在**??
過兩篇之後我們會根據原理,簡單的程式設計實現鍊錶,只有自己動手幹才能真正了解它的原理,學程式設計可不能手懶。
資料結構與演算法 鍊錶
題目 合併兩個已經排序好的鍊錶 非遞迴和遞迴兩種 方法1 cpp view plain copy print color 000000 合併鍊錶.cpp 定義控制台應用程式的入口點。include stdafx.h include using namespace std struct listnod...
資料結構與演算法 鍊錶
在講述鍊錶之前讓我們對資料結構進行乙個簡單的回顧 我們知道,資料結構指的是描述實際問題中各個資料項節點之間的前後邏輯結構關係,即要麼是線性結構 即某一資料項的前繼節點和後繼節點有且只有乙個 要麼是非線性結構 即某一資料節點的前驅或者後繼節點不止乙個 在確定了實際資料項的資料結構之後,我們要採用某種儲...
資料結構與演算法 鍊錶
反轉鍊錶 def reverse head q none p heap while p temp p.next p.next q q pp temp return p判斷鍊錶環 def meetingnode head if not head return slow head fast head.n...