題目:寫出乙個函式,給定乙個鍊錶的頭節點,反轉該鍊錶並輸出其頭節點
struct node
*linklist
對於煉表頭和鍊錶尾,也有多種定義方式。比如:
linklist list;
int value = list-
>value;
//第乙個元素
node *secondnode = list-
>next;
//下乙個節點
node *tail = lastnode;
//假設lastnode為鍊錶最後乙個元素
tail-
>next==
nullptr
;//tail的下乙個節點為空指標
linklist list;
node *firstnode = list-
>next;
//第乙個元素節點
node *tail = lastnode-
>next;
//尾指標為最後乙個節點的下乙個元素
tail-
>next==
nullptr
;
當鍊表為空鍊錶的時候,頭指標的下乙個元素為尾指標。
此題為方便起見,採用第一種定義,煉表頭定義為鍊錶的第乙個節點,尾定義為鍊錶的最後乙個節點。
鍊錶的操作比較複雜,其中包含大量指標操作,稍有不慎就會出錯。為了分析清楚,下邊畫圖來進行分析。
假設a為需要反轉的鍊錶,b為反轉過程進行到c的時候。可以看到,原本c的下乙個元素是d,反轉要求c的下乙個元素指向b,但是如果直接進行操作的話,c和d之間就發生斷裂,再也無法找到d的位址。所以在反轉之前要先儲存d的位址。
同樣地,當鍊表進行到c時,此時由於是單向鍊錶,無法回頭找到b元素的位址,因此在進行到c之前,需要把b的位址儲存下來。
下邊看看鍊錶的首尾如何處理。對於頭結點,其反轉後變為尾節點,其下乙個元素應為空節點,也就是頭結點的mprev設定為空就可以了。
對於尾節點,其下乙個節點為空,因此反轉過程可以進行到某個節點的下個節點為空指標時停止,此時該節點即為頭結點,將其反轉後輸出即可。
實現**如下:
typedef
struct listnode
*linklist;
void
reverselinklist
(linklist &list)
linklist pprev =
nullptr
; linklist pnext =
nullptr
;while
(list-
>next!=
nullptr
) list-
>next = pprev;
}
演算法是直接對輸入的鍊錶進行操作,操作完成後的鍊錶為已經反轉的鍊錶。
首先對輸入進行判斷,如果鍊錶為空指標,則不用反轉直接返回。
如果鍊錶只有1個元素,則也不用反轉,list->next為空,不會程式中的while迴圈,直接返回。
當鍊表元素多於兩個時,對於鍊錶的第乙個節點,先儲存其下乙個節點到pnext,再將list->next設定為mprev,也就是空指標。此時反轉已完成,將自身節點儲存為mprev後,進入下乙個節點。
進入下乙個節點時,會判斷該節點的是否為尾節點,如果不是迴圈一直進行。如果是,則退出迴圈,直接將節點node->next設定為pprev即完成。
反轉鍊錶容易出錯的地方有幾個:
6 劍指offer 翻轉鍊錶
class solution 如果head為null的時候,pre就為最後乙個節點了,但是鍊錶已經反轉完畢,pre就是反轉後鍊錶的第乙個節點 直接輸出pre就是我們想要得到的反轉後的鍊錶 return pre 第二種方法是 遞迴方法 struct listnode class solution 2 ...
劍指Offer16翻轉鍊錶
題目 定義乙個函式,輸入乙個鍊錶的頭結點,翻轉該鍊錶並輸出翻轉後鍊錶的頭結點。分析 這個題剛看的時候可能會和之前遇到的逆序輸出鍊錶差不多,不過在那個題目中並沒有改變鍊錶的指標,而是通過增加空間來進行逆序輸出的,還記得怎麼做嗎?當然就是增加乙個n長度的棧。當然如果題目要求中是可以改變鍊錶的,並且只允許...
劍指Offer 16 翻轉鍊錶
題目 定義乙個函式,輸入乙個鍊錶的頭結點,翻轉該鍊錶並輸出翻轉後的鍊錶。思路 1.使用兩個指標a,b分別指向待翻轉的兩個結點,同時為了防止斷鏈,使用乙個指標c儲存b next指標,c b next。2.a,b兩個結點翻轉後,令a b,b c。3.迴圈1,2直至b為null。注意 1.頭結點的next...