每一個節點都有一個向后的指針(引用)指向下一個節點,最后一個節點指向NULL表示結束,有一個Head(頭)指針指向第一個節點表示開始。如下圖:
§單鏈表的特點
耗子戴眼鏡,鼠目寸光
我們只能拿到頭節點,(在不逐個遍歷的情況下),后面還有多少個節點,它們是什么,它們在哪里,誰是最后一個節點?這些我們統統都無法知道。
肉包子打狗,有去無回
遍歷時只能從前往后,是單向的,一旦錯過某個節點,只能從頭再遍歷一次,確保這次不要錯過。
§節點的增/刪/交換
增加節點
此時必須有兩個指針,一個指向插入位置前的那個節點,稱它為prev指針,一個指向待插入的節點,稱它為node指針。如下圖:
插入過程相等於鏈接的斷開與重建。如下圖:
用代碼表示:
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列式存儲(圖解)
(完)
編程新說
用獨特的視角說技術