對遞迴模型的理解
阿新 • • 發佈:2019-01-11
一.遞迴模型
分而治之的思想也就是典型的遞迴思想,遞迴思想的核心就是遞迴模型的建立,遞迴模型就是處理這類問題的一個相同的框架,這個框架不僅僅是處理總問題的框架,也是處理組成總問題的子問題的框架,這個框架具有公用性,要適用這種公用性,就可以推斷得出,這類問題的結構就有遞迴性質(從前有座上,山上有座廟,廟裡有個老和尚,老和尚對小和尚說:從前有座上,山上有座廟,廟裡有個老和尚,老和尚對小和尚說。。。。。。。)
由此可以得出處理遞迴方法的套路:找出一個通用模型:
通用模型
{
是保證可以把母問題劃分為規模比原問題小的子問題;體現分而治之的分;
【遞迴的出口】
保證遞迴是可窮盡的,在窮盡處實現分而治之的治(第一次治)(把複雜問題轉換為簡單子問題再進行處理,)到達出口,在處理(治)完成以後,會自動返回;
【遞迴的處理】
也就是分而治之的“治”,在每個級別規模的問題中都用共同的一套遞迴處理,只不過實現順序有先後之分,注意遞迴出口的處理和遞迴處理其實是不同的,遞迴出口處的處理一般是結束返回,以邊界值判斷,而遞迴處理是一套共用的處理方法;
【遞迴三要素的順序關係】
我們通常判斷遞迴出口條件以決定遞迴是否向下執行的先決條件,然後才是遞迴的傳遞和遞迴的處理(後兩者順序依情況而定),這裡遞迴出口有兩種形式:
1.遞迴出口的型別
(1)返回型出口(一定要注意返回值不要丟失)
例1:求二叉樹的高度的遞迴演算法:
![](https://img-blog.csdn.net/20161118172639184?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
上述型別的錯誤非常容易出現:出現的原因是對return返回理解的不透徹造成的;
return返回的接收者:只能返回給呼叫自己那個函式,不會越級返回給父函式的上一層或上上層,總的一句話:誰呼叫返給誰;
上述的程式碼中,在遞迴的出口處(注意,這個出口是由兩個出口組成的:當subtree為空或者找到了父節點(subtree->leftnode
== current || subtree->rightnode == current))進行返回,這個返回只會給呼叫它的父函式, 父函式如果想繼續向上傳遞,必須自己再次返回,否則,返回值丟失;
正確程式碼示範:
![](https://img-blog.csdn.net/20161118172727169?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
紅色標註是父函式自己的返回;
(2)邏輯型出口
例:
![](https://img-blog.csdn.net/20161118172800342?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
if(i>0)就是邏輯型出口,不做任何返回,這種上一層實現不依賴下一層結果的遞迴最好用迴圈代替(節省空間) 2.遞迴出口、遞迴處理、遞迴傳遞三者的順序關係 遞迴的傳遞:保證遞迴分治思想,即把大問題劃分為同等結構的子問題; 遞迴出口: 確保遞迴傳遞的可窮盡性,所以肯定在遞迴傳遞之前; 遞迴處理: 遞迴的使用場景一般是上一層的結果的計算需要依賴下一層的結果,所以遞迴的處理一般在遞迴的傳遞之後(傳遞下去再返回才能進行這層的計算); 所以一般遞迴的模型中這三者的順序如下: 遞迴{ 1 遞迴的出口; 2 遞迴的傳遞; 3 遞迴的處理; } 這只是一般通常的情況,也有不同,比如上面尋找二叉樹父節點的遞迴就是遞迴的處理在遞迴的傳遞之前,為什麼呢?查詢操作肯定是查到立刻返回,就沒必要遍歷全部結點了(沒必要向下傳遞了)且結果沒有依賴性(結果的得出沒有次序性),上層遞迴只是負責傳遞下層返回的引數,自己不加工。 二.常見的使用遞迴的場景 (1)二叉樹:二叉樹的結構就是遞迴的,所以對他的操作一般考慮遞迴 二叉樹前中後序遍歷; 二叉樹的高度; 二叉樹的映象; 二叉樹的個數; 二叉樹的最大值; 二叉樹的刪除; 二叉樹的尋父節點; 二叉樹的建立: 二叉樹的複製; (2)階乘: 三.遞迴形象的理解 (1)查單詞: 遇到一個不理解的單詞,維基百科上查解釋,在這個解釋中又有不理解的單詞,又去查這個單詞的解釋。。。。。。終於有一個詞條裡每個詞都能看懂了,這時候就返回,繼續看上一個詞的解釋。 (2)遞紙條: 上課傳紙條,你傳給你的右手邊,右上邊的人又傳給他的右手邊人。。。。紙條傳到了,寫上回話(遞迴出口)後,就往回傳(遞迴返回)
- 遞迴的傳遞
- 遞迴的出口(隱含了遞迴的返回)
- 遞迴的處理
- 遞迴出口的處理:return 0;
- 遞迴處理: return i > j ? i + 1 : j + 1;
if(i>0)就是邏輯型出口,不做任何返回,這種上一層實現不依賴下一層結果的遞迴最好用迴圈代替(節省空間) 2.遞迴出口、遞迴處理、遞迴傳遞三者的順序關係 遞迴的傳遞:保證遞迴分治思想,即把大問題劃分為同等結構的子問題; 遞迴出口: 確保遞迴傳遞的可窮盡性,所以肯定在遞迴傳遞之前; 遞迴處理: 遞迴的使用場景一般是上一層的結果的計算需要依賴下一層的結果,所以遞迴的處理一般在遞迴的傳遞之後(傳遞下去再返回才能進行這層的計算); 所以一般遞迴的模型中這三者的順序如下: 遞迴{ 1 遞迴的出口; 2 遞迴的傳遞; 3 遞迴的處理; } 這只是一般通常的情況,也有不同,比如上面尋找二叉樹父節點的遞迴就是遞迴的處理在遞迴的傳遞之前,為什麼呢?查詢操作肯定是查到立刻返回,就沒必要遍歷全部結點了(沒必要向下傳遞了)且結果沒有依賴性(結果的得出沒有次序性),上層遞迴只是負責傳遞下層返回的引數,自己不加工。 二.常見的使用遞迴的場景 (1)二叉樹:二叉樹的結構就是遞迴的,所以對他的操作一般考慮遞迴 二叉樹前中後序遍歷; 二叉樹的高度; 二叉樹的映象; 二叉樹的個數; 二叉樹的最大值; 二叉樹的刪除; 二叉樹的尋父節點; 二叉樹的建立: 二叉樹的複製; (2)階乘: 三.遞迴形象的理解 (1)查單詞: 遇到一個不理解的單詞,維基百科上查解釋,在這個解釋中又有不理解的單詞,又去查這個單詞的解釋。。。。。。終於有一個詞條裡每個詞都能看懂了,這時候就返回,繼續看上一個詞的解釋。 (2)遞紙條: 上課傳紙條,你傳給你的右手邊,右上邊的人又傳給他的右手邊人。。。。紙條傳到了,寫上回話(遞迴出口)後,就往回傳(遞迴返回)