1. 程式人生 > >對遞迴模型的理解

對遞迴模型的理解

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