想起很早以前某次面試,面試官很嚴肅的要求我現場手寫單鏈表反轉的**。哥虎軀一震,心想:不就需要要個臨時變數來記錄位址嗎,用得著這樣煞有介事?雖然在那之前我的確沒寫過這個程式,哈哈哈…
當時我草草寫了十來行**,面試官不等我完成,就直接拿過去開始問問題。不知道是不是因為抗壓能力不足,在面試官的不斷『盤問』下,哥越來越緊張,到最後簡直頭腦一片空白,無法正常思考問題,回答問題就越來越心虛——當然,面試的結果就可想而知了。現在回想起來,除了心理素質差之外,還有個比較根本的原因:自己平時動手少,導致底氣不足。現在再來寫一寫,當作紀念吧。
本著思路要清晰的原則,再來分析一下問題:鍊錶反轉,目的是讓『箭頭』反向,但單鏈表的特點決定了,在反轉過程中,需要『記住』相關節點的位址,否則會引起資訊丟失,無法開展後續步驟。
簡單畫一下:
由圖可知,從狀態一轉換到狀態二,就是反轉操作的一般步驟。
我們可以用兩個變數來分別儲存「當前位置」和「下一位置」(記為current, next),以及乙個輔助變數(記為temp), 然後按照如下步驟來進行操作:
1. 將temp複製為next的後驅節點,也就是y;
2. 將next的後驅節點置為current,也就是a;
3. 將curren賦值為next,就是b;
4. 將next賦值為temp,也就是y。
這樣,我們就到達了狀態二。
觀察一下操作步驟,temp、next的後驅節點、current、next這四者,賦值表示式形成了乙個閉合的環,其實就相當於陣列的迴圈移位操作。
解決了一般操作之後,我們接下來需要考慮的就是初始狀態、結尾判斷等邊界情況了。
下面開始貼**:
/************************
* reverselinkedlist.cpp
***********************/
#include #include //節點定義.
typedef struct _linkedlistnode
linkedlistnode;
//建立新節點.
linkedlistnode* createnode(int data)
return newnode;
}//建立測試所用鍊錶.
linkedlistnode* createlinkedlist(int nodenum)
return head;
}//反轉函式.
linkedlistnode* reverselinkedlist(linkedlistnode* node)
//將原有頭結點的next成員設定為空.
node->next = 0;
//完成後,current即為新鍊錶的頭結點.
return current;
}//列印鍊錶.
void printlinkedlist(linkedlistnode* node)
printf("\n");
}//刪除鍊錶.
void deletelinkedlist(linkedlistnode* node)
}//測試函式.
void testreverse(int nodenum)
int main()
執行結果:
單鏈表反轉
單鏈表反轉,可以用迴圈做,當然也可以遞迴 詳見 include includestruct node 3 1 4 6 2 1 1 3 4 6 2 2 4 1 3 6 2 3 6 4 1 3 2 4 2 6 4 1 3 5 迴圈反轉,即依次改動3個指標值,直到鍊錶反轉完成 比如,上面第 1 行到第 2...
反轉單鏈表
include stdafx.h include include using namespace std struct listnode typedef listnode plistnode typedef plistnode list list creatlist return head void...
單鏈表反轉
挺簡單的經典題,自己寫的第乙個版本,變數初始化是這麼做的,pprevs phead,pcurrent phead next,看著也覺得怪怪的。最後review的時候,發現這樣不會把反轉前第乙個節點的next置空!修正版本 include stdafx.h include using namespac...