資料結構69 鍊錶逆置,鍊錶反轉,鍊錶翻轉

2022-07-07 18:42:11 字數 3993 閱讀 8431

鍊錶翻轉,簡單地理解,就是將鍊錶的頭部結點變為鍊錶的尾部結點,與此同時將原鍊錶的尾部結點變成頭部結點。如下圖所示:

圖 1 鍊錶翻轉示意圖

將鍊錶進行翻轉的方法有多種,本節給大家介紹兩種實現方法。

實現鍊錶翻轉最直接的方法就是:從鍊錶的頭部開始遍歷每個結點,改變每個結點的指向,即將原本指向下乙個結點的指標改為指向上乙個結點。

唯一比較特殊的是,鍊錶中的首元結點(第乙個結點)前面沒有結點,所以在改變其指標指向的時候,要將其指標指向 null。

具體實現過程為:

首先設定乙個新的鍊錶,用於接收舊煉表上的結點,該新鍊錶初始狀態為乙個空鍊錶,如下圖所示:

圖 2 鍊錶翻轉過程一

遍歷原鍊錶,將結點依次插入到新鍊錶的頭部。要完成這一步操作,我們需要新新增兩個指標(分別命名為 p 和 temp):

新新增指標 p 和 temp 後的鍊錶,如下圖所示:

圖 3 鍊錶翻轉過程二

以上的準備工作完成,鍊錶的翻轉就可以開始了。在遍歷原鍊錶的過程中,對每個結點都做如下操作:

注意:第一步必須要在第四步的前面,否則會導致最終temp指向 null 的next,發生錯誤。

遍歷每個結點的過程示意圖如下:

翻轉結點 1 ,則圖 3 經過以上 4 步調整後,變為:

圖 4 翻轉結點 1

翻轉結點 2,則上圖經過 4 步調整後,變為下圖:

圖 5 翻轉結點 2

翻轉結點 3 時,則上圖經過 4 步調整後,變為下圖:

圖 6 翻轉結點 3

當翻轉完最後乙個結點 3 之後,由於指標 p 指向的為 null ,說明沒有結點可以翻轉,即遍歷結束。(指標 p 為null ,為遍歷結束的判斷條件)。

link *reverselink(link *h)

// 建立指標 p 作為遍歷鍊錶的指標

link *p =h;

// 建立乙個新的鍊錶,用於儲存翻轉鍊錶,只不過該鍊錶初始狀態為null

link *newh =null;

// 遍歷指標 p 為 null 作為遍歷結束的標誌

while(p !=null)

return

newh;

}

另一種方法較前一種比較複雜,需要使用到遞迴的思想。

方法一是依次遍歷鍊錶,更改每個結點的指向,最後乙個結點為翻轉鍊錶的頭部結點。而方法二則完全倒過來,其實現過程為:先通過遞迴的思維找到鍊錶的頭部,然後再改變每個結點的指向,最終到達鍊錶翻轉的目的。

方法二的**實現函式為:

// 

鍊錶翻轉的函式

link *reverselist(link *h)

// 遞迴查詢新鍊錶的頭,找到用賦值給 newh

link *newh = reverselist(h->next);

// 遞迴完成後,h 初始狀態為 newh 的上乙個結點。

// 在一步步彈棧的過程中,始終另 h 指向的結點作為新鍊錶的最後乙個結點

h->next->next = h;

// h->next = null;

// 返回新鍊錶所指頭部的指標。

return

newh;

}

**執行過程分析:

4-6行:對於給定的指標 h ,首先判斷指標 h 是否存在,如果指標 h 不存在,或者指標 h 只含有乙個結點,則直接返回,即指標 h 不需要翻轉;

第 8 行:函式體內呼叫自身,是典型的遞迴。通過不斷查詢指標 h 所指結點的下乙個結點,最終會找到鍊錶的最後乙個結點作為函式的返回值,而此結點恰恰就是翻轉後鍊錶的首元結點(第乙個結點),所以我們用乙個新指標 newh 來充當新鍊錶的頭指標。

當通過遞迴找到對應的 newh 結點時,相應地,引數指標 h 也被遞迴至 newh 所指結點的上一結點處,如下圖所示:

圖 7 遞迴結束時的示意圖

注意:頭指標 h 和引數指標 h 完全不是一碼事,作用域不同:引數 h 只在函式體內有效,而頭指標 h 為主函式中宣告。

第 11行到最後:此部分**為指標 h 逐層返回時才會執行的**,在逐層返回的過程中,通過不斷地將h所指結點賦值給 h->next->next,並且每次賦值結束後,都取消 h 所指結點的指向,最終達到翻轉鍊錶的目的。

自圖 7 開始,在指標 h 第一次返回時,此部分的**執行示意圖為:

指標 h 再次返回時,此部分的**執行示意圖為:

最終完成了鍊錶的翻轉,函式返回新鍊錶的頭指標 newh 。

#include #include 

typedef

struct

link

link;

link *initlink();  

// 建立首元結點

link *head=(link*)malloc(sizeof

(link));

head->count = element[0

];  

// for迴圈中需要乙個指標temp,從頭結點開始依次鏈結新建立的結點

link *temp = head;

// for迴圈逐個建立鍊錶,並用temp兩兩鏈結

for (int i=1; i<3; i++)

return

head;

}//

方法一實現鍊錶翻轉

link *reverselink(link *h)

// 建立指標 p 作為遍歷鍊錶的指標

link *p =h;

// 建立乙個新的鍊錶,用於儲存翻轉鍊錶,只不過該鍊錶初始狀態為null

link *newh =null;

// 遍歷指標 p 為 null 作為遍歷結束的標誌

while(p !=null)

return

newh;

}//

方法二實現鍊錶翻轉

link *reverselist(link *h)

// 遞迴查詢新鍊錶的頭,找到用賦值給 newh

link *newh = reverselist(h->next);

// 遞迴完成後,h 初始狀態為 newh 的上乙個結點。

// 在一步步彈棧的過程中,始終另 h 指向的結點作為新鍊錶的最後乙個結點

h->next->next = h;

// h->next = null;

// 返回新鍊錶所指頭部的指標。

return

newh;}//

遍歷鍊錶的輸出函式

void display(link *h)

printf("\n

");}int

main ()

執行結果:

123321

123

資料結構 鍊錶的逆置

將乙個鍊錶進行逆置 如 10 20 30 40 逆置後40 30 20 10 分析 方法一 新建鍊錶 遍歷舊鍊錶,將舊鍊錶的結點依此頭插到新鍊錶中。上 include include typedef struct node node 建立結點 node buynode int data 用建立新鍊錶...

資料結構實驗之鍊表三 鍊錶的逆置

time limit 1000ms memory limit 65536k 輸入多個整數,以 1作為結束標誌,順序建立乙個帶頭結點的單鏈表,之後對該單鏈表的資料進行逆置,並輸出逆置後的單鏈表資料。輸入多個整數,以 1作為結束標誌。輸出逆置後的單鏈表資料。12 56 4 6 55 15 33 62 1...

資料結構實驗之鍊表三 鍊錶的逆置

資料結構實驗之鍊表三 鍊錶的逆置 輸入多個整數,以 1作為結束標誌,順序建立乙個帶頭結點的單鏈表,之後對該單鏈表的資料進行逆置,並輸出逆置後的單鏈表資料。輸入多個整數,以 1作為結束標誌。輸出逆置後的單鏈表資料。12 56 4 6 55 15 33 62 1 62 33 15 55 6 4 56 1...