演算法之遞迴(2)- 連結串列遍歷
(3條訊息) 演算法之遞迴(2)- 連結串列遍歷_weixin_30951231的部落格-CSDN部落格
https://blog.csdn.net/weixin_30951231/article/details/99482611
在遞迴(1)中,簡單的介紹了遞迴的思想,並且通過一個例子簡單闡述了遞迴是如何工作的,並且遞迴的實現是以線性結構來表示的。之所以用線性的,是因為其易於理解;如果使用樹結構,將加大對問題的難度,不利於初學者理解遞迴的思想。
為什麼用遞迴
關於為什麼用遞迴,我個人的理解是遞迴不要違背演算法的初衷,即期待傳入xxx值,加工後返回xxx值。不要為了遞迴而遞迴,容易造成對函式語義的奇異。另外,通過遞迴,可以讓程式碼更加整潔,短小,精湛,優美。當然,還會存在一定程度的效能損耗;不過,合理的使用,對於那部分的損耗可以忽略不計。
讓我們以單鏈表為例,理解一下遞迴是如何工作的。
1.遍歷單鏈表
迴圈 |
遞迴 |
private void TraveserL(LNode head) { if (head == null) return; while (head != null) { Console.WriteLine(p.data); p = p.next; } } |
|
對於迴圈遍歷我想不用多說了吧。不過,值得注意的是遞迴的遍歷,先對資料進行列印,然後遍歷下一個節點。有趣的是,如果將列印語句放在遞迴呼叫的後面,將是一個逆序的列印。
分析
假設連結串列的結構是這樣的
A->B->C->D->E->F
遞迴呼叫時將發生如下情形
1.在遞迴呼叫之前列印(意味著進入函式體的時候列印)
(1)進入函式(從左到右讀)
A-> |
B-> |
C-> |
D-> |
E-> |
F-> |
列印A |
列印B |
列印C |
列印D |
列印E |
列印F |
輸出:A, B, C, D, E, F.
(2)當函式退出(從右到左度)
<-A |
<-B |
<-C |
<-D |
<-E |
<-F |
空 |
空 |
空 |
空 |
空 |
空 |
2.在遞迴呼叫之後(意味著只有退出函式體的時候,才進行列印)
(1)進入函式體(從左到右讀)
A-> |
B-> |
C-> |
D-> |
E-> |
F-> |
空 |
空 |
空 |
空 |
空 |
空 |
(2)退出出函式體(從右到左讀)
<-A |
<-B |
<-C |
<-D |
<-E |
<-F |
列印A |
列印B |
列印C |
列印D |
列印E |
列印F |
輸出:F, E, D, C, B, A
結論,當操作在遞迴呼叫之後進行,那麼是從後向前對連結串列執行操作。這也是棧的特性之一。當然,具體何時決定,取決與程式設計師自己,是想從頭開始順序操作,還是後到前逆序操作,具體問題具體分析。
轉載於:https://www.cnblogs.com/lucasluo/archive/2012/07/30/2615902.html