資料結構基礎--連結串列

ofollow,noindex">目錄
- 基本性質
- 連結串列的分類
- 按連線方向分類
- 按照有無迴圈分類
- 連結串列問題程式碼實現的關鍵點
- 連結串列插入和刪除的注意事項
- 連結串列翻轉
- 向一個有序的環境連結串列中插入一個節點,並保持依舊有序
- 對於一個單鏈表,在不給定head的情況下刪除指定node。要求時間複雜度O(1)
- 給定一個連結串列,與一個數組num。要求實現荷蘭國旗
- 給定兩個有序連結串列的head,列印共同部分
- 給定一個單鏈表的head,實現一個調整連結串列的函式,使得每K個節點之間逆序,如果最後不足K個,則不調整
- 判斷一個連結串列是否為迴文結構
- 判斷一個單鏈表是否有環,如有則返回入環節點。時間複雜度O(N),額外空間複雜度O(1)
- 兩個無環單鏈表是否相交,時間複雜度O(N+M),額外空間複雜度O(1)
- 判斷兩個有環單鏈表是否相交,時間複雜度O(N+M),額外空間複雜度O(1)
- 判斷兩個連結串列是否相交,並返回第一個相交的節點
基本性質
-
連結串列問題演算法難度不高,但考察程式碼的實現能力
-
連結串列和陣列一樣,都是一種線性結構
- 陣列是實體地址上一段連續的儲存空間。
可以通過下標直接獲取元素
當內容超出容量時需要重新定義陣列。 - 連結串列空間不一定保持聯絡,為臨時分配的。
只能從連結串列的頭部開始一個一個查詢
增刪的效率高於陣列,因為不需要更改記憶體結構
連結串列的分類
-
按連線方向分類
- 單鏈表
每個節點只能通過next指標
,指向下一個節點。 - 雙鏈表
除了next指標
之外,還有一個prev指標
指向其上一個節點。
-
按照有無迴圈分類
-
普通連結串列
頭無prev,尾無next。
-
迴圈連結串列
首尾相接的連結串列。
最後一個節點的next指標指向其第一個節點
對於雙鏈表,其第一個節點的prev指標指向最後一個節點。
連結串列問題程式碼實現的關鍵點
-
連結串列調整函式的返回值,往往是節點型別
連結串列在調整過程中往往遇到改變頭部的情況,如果頭節點被改變則需要返回一個新頭部。
-
在調整連結串列的過程中,先採用畫圖的方式理清邏輯
注意那些指標變化了,同時注意對前後節點的影響。
-
邊界條件的處理
頭節點,尾節點,空節點的特殊處理。
連結串列插入和刪除的注意事項
-
特殊處理連結串列為空或長度為1
-
插入過程的調整
取得前後節點,將前節點的next指向新節點,新節點的next指向後節點。

-
刪除過程的調整
取得前後節點,將前一個節點的next指標指向後一個節點。

-
頭尾插入或刪除
在邏輯的設計上應該考慮空節點的情況
連結串列翻轉
-
特殊處理連結串列為空或長度為1
-
單鏈表的翻轉
已翻轉的頭節點head,下一個節點now
- 將now節點的next指向head
- 將now節點設定為已翻轉部分的新head
需要注意在執行1,2步驟之前需要一個變數來儲存原now節點的next節點。
步驟2設定了新的head之後,將該節點作為新的now,繼續翻轉。

向一個有序的環境連結串列中插入一個節點,並保持依舊有序。
要求時間複雜度O(N),額外空間複雜度O(1)。
-
如果連結串列為空
讓新節點node自己成為環形連結串列,並返回node即可。
-
如果連結串列不為空
令變數 prve
設為頭節點, current
設為第二個節點,兩個節點同步移動。
-
當有
node<=prve && node>=current
,則說明node應該插入二者之間 -
若prve回到head但依舊沒有合適的位置插入
說明node為最大值或最小值,插入head之前即可。
需要區分為兩種情況下是否出現新的head,並返回。

對於一個單鏈表,在不給定head的情況下刪除指定node。要求時間複雜度O(1)
-
如果node.next不為空,也就是node不是尾節點
如果工程允許,可以將node.next的內容copy到node節點上,變相的刪除了node節點的資料。
-
如果node是尾節點
給定一個連結串列,與一個數組num。要求實現荷蘭國旗
-
將連結串列遍歷成陣列,然後進行荷蘭國旗排序,最後還原成連結串列。
-
遍歷連結串列的過程中使用三個小連結串列。小於,等於,大於。最後將三個連結串列串聯。
給定兩個有序連結串列的head,列印共同部分
-
有一個為空直接返回
-
採用外排的方式,直到有一個為空則停止。
給定一個單鏈表的head,實現一個調整連結串列的函式,使得每K個節點之間逆序,如果最後不足K個,則不調整。

-
連結串列為空,長度<k或者k<2
直接返回
-
通過棧結構,實現逆序

- 需要保留上次逆序的最後一位元素,修改其next。
- 最後段不足k個,直接不修改。值將上次逆序的最後一個元素next設定好。
- 第一組的第一個節點為頭節點。
-
不使用棧結構,手動逆序
判斷一個連結串列是否為迴文結構

-
將連結串列節點依次入棧,在彈出時與原連結串列依次比對。
-
使用快行指標,通過二倍速的方式遍歷。依次將慢指標的節點壓入棧中,當快節點遍歷到末尾時,慢指標正好處於中間位置。
繼續移動慢指標,並與棧中彈出的元素做對比。(需要注意總量的奇偶)
-
將後半部分連結串列進行逆序處理,從兩端同時進行遍歷比對
判斷一個單鏈表是否有環,如有則返回入環節點。時間複雜度O(N),額外空間複雜度O(1)
如果不要求額外空間複雜度,可以直接用雜湊表比對。
-
使用快行指標的方式
如果兩指標相遇則表示有環,此時將快指標改為1,並從head重新同步移動, 相遇處即為入環位置 或者還有 另一個證明 。
兩個無環單鏈表是否相交,時間複雜度O(N+M),額外空間複雜度O(1)
先遍歷兩個連結串列確定長度,然後另長連結串列從短連結串列開始位置與短連結串列再次同步遍歷,檢視是否相同。

判斷兩個有環單鏈表是否相交,時間複雜度O(N+M),額外空間複雜度O(1)
首先都需要先去定單獨的入環節點,然後
-
是否入環之前已經相交
-
是否入環時才相交,則入環位置節點相同
-
迴圈其中一個環,若遇到另一個的入環節點則返回。
-
否則,兩連結串列並未相交
判斷兩個連結串列是否相交,並返回第一個相交的節點
-
嘗試找到各自的入環節點
-
若一個有環一個無環,則不相交
-
若都為無環,則按照上文《兩個無環單鏈表是否相交》的方式查詢
-
若都為有環,則按照上文《判斷兩個有環單鏈表是否相交》的方式查詢