10年架構師圖解單鏈表,一篇圖文徹底搞懂
每一個節點都有一個向後的指標(引用)指向下一個節點,最後一個節點指向NULL表示結束,有一個Head(頭)指標指向第一個節點表示開始。如下圖:
§單鏈表的特點
耗子戴眼鏡,鼠目寸光
我們只能拿到頭節點,(在不逐個遍歷的情況下),後面還有多少個節點,它們是什麼,它們在哪裡,誰是最後一個節點?這些我們統統都無法知道。
肉包子打狗,有去無回
遍歷時只能從前往後,是單向的,一旦錯過某個節點,只能從頭再遍歷一次,確保這次不要錯過。
§節點的增/刪/交換
增加節點
此時必須有兩個指標,一個指向插入位置前的那個節點,稱它為prev
插入過程相等於連結的斷開與重建。如下圖:
用程式碼表示:
node.next = prev.next
prev.next = node
刪除節點
此時最好有兩個指標,一個指向待刪除節點前的那個節點,稱它為prev指標,一個指向待刪除節點,稱它為node指標。如下圖:
用程式碼表示:
node = prev.next
prev.next = node.next
node.next = NULL
交換節點
此時必須有兩個指標,一個指向待交換的兩個節點前的那個節點,稱它為prev指標,一個指向待交換的兩個節點中的第一個節點,稱它為first指標。如下圖:
用程式碼表示:
first = prev.next
prev.next = first.next
first.next = prev.next.next
prev.next.next = first
§逆序
將連結串列的順序倒過來。有兩種方法:依次交換法,集體向後轉法。
依次交換法
1先和2交換,再和3交換,再和4交換,再和5交換,現在1已經在最後了,2是第一個。如下圖:
2先和3交換,再和4交換,再和5交換,此時2已經是倒數第二個了,3是第一個。如下圖:
依次類推,用3進行一輪交換,再用4進行一輪交換,逆序就完成了。如下圖:
感覺和氣泡排序法有些神似。
集體向後轉法
這種方法的思路來自於體育課。一排縱隊和體育老師面對面站著。老師就是頭節點,縱隊就是單鏈表。
縱隊集體向後轉,老師再走過去和新縱隊面對面。單鏈表換了方向,頭節點換了指向。
需要三個指標,一個指向已經向後轉過的部分,稱為done指標;一個指向正要向後轉的那個節點,稱為doing指標;一個指向剩餘待向後轉的部分,稱為todo指標。
一開始還沒有一個向後轉的,因此done = NULL,doing指向第一個,即doing = head,todo指向第二個,即todo = doing.next。如下圖:
讓正在向後轉的節點(即doing)的next指標指向已經向後轉過的(即done);done,doing,todo三個指標分別向右移動一個節點。如下圖是操作過程和操作後的結果:
用程式碼表示:
doing.next = done
done = doing
doing = todo(如果doing是NULL,結束)
todo = todo.next(如果next是NULL,則賦NULL)
同理,再進行一步,如下圖:
同理,最後一步,結束後即完成逆序。如下圖:
兩種方法的比較,一是連結串列的方向不變,變換節點位置;二是節點位置不變,變換連結串列的方向。
§LeetCode,以K個節點為一組逆序
這是leetcode中linkedlist部分的一道題,級別是hard。
如果k=3,每3個節點逆序一下,直到結尾,如果最後剩餘的節點不夠3個,則原樣保留。
第一步,0、1、2逆序
第二步,3、4、5逆序
第三步,6、7、8逆序
第四步,9原樣保留
要求:只能定義常量個數的額外變數(或者說只能使用額外常量的記憶體)。
PS:這道題目雖然是hard級別,但是有了以上的講解,相信大多數人都能做出來。注意邊界條件和細心即可。
相關文章
五分鐘輕鬆瞭解Hbase列式儲存(圖解)
(完)
程式設計新說
用獨特的視角說技術