1. 程式人生 > >全面分析再動手的習慣:連結串列的反轉問題(遞迴和非遞迴方式)

全面分析再動手的習慣:連結串列的反轉問題(遞迴和非遞迴方式)

https://www.cnblogs.com/kubixuesheng/p/4394509.html

dashuai的部落格

要麼牛B!要麼滾!

隨筆-88  文章-0  評論-167 

全面分析再動手的習慣:連結串列的反轉問題(遞迴和非遞迴方式)

討論QQ群:待定

定義一個方法(函式),實現輸入一個連結串列的頭結點,然後可以反轉這個連結串列的方向,並輸出反轉之後的連結串列的頭結點。

 

連結串列類的問題,涉及到了很多指標的操作,需要嚴謹的分析,全面的分析問題之後,在開始寫程式碼,磨刀不誤砍柴工!反轉連結串列,直接的想法,就是把連結串列中指標的方向反轉就可以了,如圖所示:

假設 i 結點之前,我們把所有的結點的指標都已經反轉了,那麼自然 i 和以後的結點連結發生了斷裂!如下圖;

這樣的話,無法繼續遍歷 i 以後的結點了,那麼自然想到,在斷鏈之前,提前儲存之前的狀態。那麼自然想到定義三個指標,分別指向當前結點 i,i 的後繼 j,i 的前驅 h 結點。儲存斷鏈之前的三個結點的連線狀態。然後,假設沒問題了,那麼繼續反轉完畢,最後連結串列的尾結點就是反正連結串列的頭結點了,也就是 next 為 null 的結點,是原始連結串列的尾結點。

複製程式碼

 

複製程式碼

定義的這個三個指標,目的就是防止斷鏈之後無法繼續遍歷連結串列以後的結點,實現全部的反轉。當 pnow 的 next 指向 pnow 的前驅pre(初始化是 null)的時候,已經實現了 pnow 和前驅pre的方向反轉,但是 pnow 此時就和後繼pnext斷鏈了,那麼使用 pre 後移的方式,指向 pnow,同時 pnow 也後移,指向 pnext,而 pnext 繼續指向更新之後的 pnow 的 next 結點即可。從而實現了狀態的儲存,繼續遍歷全部結點,實現連結串列反轉。

注意關於連結串列問題的常見注意點的思考:

1、如果輸入的頭結點是 NULL,或者整個連結串列只有一個結點的時候

2、連結串列斷裂的考慮

下面看看遞迴的實現方式

遞迴的方法其實是非常巧的,它利用遞迴走到連結串列的末端,然後再更新每一個node的next 值 ,實現連結串列的反轉。而newhead 的值沒有發生改變,為該連結串列的最後一個結點,所以,反轉後,我們可以得到新連結串列的head。

複製程式碼

 

複製程式碼

程式剛開始執行,if 語句失效,進入 else 語句,然後執行Node *newhead = reverseList(head->next);第二個結點的指標引數傳入遞迴函式,一直到,最後一個結點的指標引數傳入遞迴函式,if 語句有效head->next == NULL,返回當前的head 給 newhead 指標指向,如圖:

其實在遞迴函式棧內,按照後進先出的順序,執行一級級的遞迴函式,返回末位結點給 newhead 之後,執行遞迴棧裡的第二個遞迴函式,發生如圖

返回 newhead,也就是新的反轉之後的連結串列(臨時的),然後進入到遞迴工作棧裡的第一個遞迴函式,如圖:

返回 newhead,也就是反轉之後的連結串列,此時遞迴工作棧的函式全部執行,返回的結點就是反轉之後的連結串列的頭結點(之前的尾結點)

 

辛苦的勞動,轉載請註明出處,如果真心幫到了您,為鼓勵更多的寫作,您可以選擇部落格右側的打賞功能。

分類: 資料結構演算法分析