一.遞迴模型
分而治之的思想也就是典型的遞迴思想,遞迴思想的核心就是
遞迴模型
的建立,遞迴模型
就是處理這類問題的乙個
相同的框架,這個框架不僅僅是處理總問題的框架,也是處理組成總問題的子問題的框架,這個框架具有公用性,要適用這種公用性,就可以推斷得出,這類問題的結構就有遞迴性質(
從前有座上,山上有座廟,廟裡有個老和尚,老和尚對小和尚說:從前有座上,山上有座廟,廟裡有個老和尚,老和尚對小和尚說。。。。。。。
)
由此可以得出處理遞迴方法的套路:
找出乙個
通用模型:
通用模型
所以乙個通用的遞迴模型就是由上面兩部分組成的;
【遞迴的傳遞】
是保證可以把
母問題劃分為
規模比原問題
小的
子問題;體現分而治之的
分;
【遞迴的出口】
保證遞迴是可窮盡的,在窮盡處實現分而治之的
治
(第一次治)(
把複雜問題轉換為簡單子問題再進行處理,)到達出口,在處理(治)完成以後,會自動返回;
【遞迴的處理】
也就是分而治之的
「治」
,在每個級別規模的問題中都用共同的一套遞迴處理,只不過實現順序有先後之分,注意
遞迴出口的處理
和
遞迴處理
其實是不同的,遞迴出口處的處理一般是結束返回,以邊界值判斷,而遞迴處理是一套共用的處理方法;
【遞迴三要素的順序關係】
我們通常判斷遞迴出口條件以決定遞迴是否向下執行的先決條件,然後才是遞迴的傳遞和遞迴的處理(後兩者順序依情況而定),這裡遞迴出口有兩種形式:
1.遞迴出口的型別
(1)返回型出口(
一定要注意返回值不要丟失
)
例1:求二叉樹的高度的遞迴演算法:
例2:尋找二叉樹任意結點的父節點
錯誤**示範:
上述型別的錯誤非常容易出現:出現的原因是對
return返回
理解的不透徹造成的;
return返回的接收者:只能返回給呼叫自己那個函式,不會越級返回給父函式的上一層或上上層,總的一句話:
誰呼叫返給誰;
上述的**中,在遞迴的出口處(注意,這個出口是由
兩個出口
組成的:當subtree為空或者找到了父節點(subtree->leftnode == current || subtree->rightnode == current))進行返回,這個返回只會給呼叫它的父函式,
父函式如果想繼續向上傳遞,必須自己再次返回
,否則,返回值丟失;
正確**示範:
紅色標註是父函式自己的返回;
(2)邏輯型出口
例:
if(i>0)就是邏輯型出口,不做任何返回,
這種上一層實現不依賴下一層結果的遞迴最好用迴圈代替(節省空間)
2.遞迴出口、遞迴處理、遞迴傳遞三者的順序關係
遞迴的傳遞:
保證遞迴分治思想,即把大問題劃分為同等結構的子問題;
遞迴出口:
確保遞迴傳遞的可窮盡性,所以肯定在
遞迴傳遞
之前;
遞迴處理:
遞迴的使用場景一般是上一層的結果的計算需要依賴下一層的結果,所以遞迴的處理一般在遞迴的傳遞之後(傳遞下去再返回才能進行這層的計算);
所以一般遞迴的模型中這三者的順序如下:
遞迴
這只是一般通常的情況,也有不同,比如上面尋找二叉樹父節點的遞迴就是
遞迴的處理
在
遞迴的傳遞
之前,為什麼呢?查詢操作肯定是查到立刻返回,就沒必要遍歷全部結點了(沒必要向下傳遞了)且結果沒有依賴性(結果的得出沒有次序性),上層遞迴只是負責傳遞下層返回的引數,自己不加工。
二.常見的使用遞迴的場景
(1)二叉樹:二叉樹的結構就是遞迴的,所以對他的操作一般考慮遞迴
二叉樹前中後序遍歷;
二叉樹的高度;
二叉樹的映象;
二叉樹的個數;
二叉樹的最大值;
二叉樹的刪除;
二叉樹的尋父節點;
二叉樹的建立:
二叉樹的複製;
(2)階乘:
三.遞迴形象的理解
(1)查單詞:
遇到乙個不理解的單詞,維基百科上查解釋,在這個解釋中又有不理解的單詞,又去查這個單詞的解釋。。。。。。終於有乙個詞條裡每個詞都能看懂了,這時候就返回,繼續看上乙個詞的解釋。
(2)遞紙條:
上課傳紙條,你傳給你的右手邊,右上邊的人又傳給他的右手邊人。。。。紙條傳到了,寫上回話(遞迴出口)後,就往回傳(遞迴返回)
對遞迴的理解
昨天和宿舍一哥們討論二叉樹中求最近公共父節點問題時,才發現原來對遞迴的理解都是錯的,其實在程式內部分配的棧和資料結構的棧功能基本一樣,當然前者的棧還涉及到棧幀,函式內部訪問某個棧幀的元素並不一定是從棧頂訪問。舉乙個簡單的例子,遍歷乙個二叉樹,無論是非遞迴演算法和遞迴演算法時間複雜度都是o n 以前認...
對尾遞迴的理解
遞迴,在程式執行過程中呼叫自己,每一級遞迴都需要呼叫函式,會建立新的棧空間,隨著遞迴深度的增加,建立的棧越來越多,造成棧的 尾遞迴基於函式的尾呼叫,每一級呼叫直接返回函式的返回值更新呼叫棧,而不是建立新的呼叫棧,類似迭代的實現,時間和空間上均優化了一般的遞迴 存在的問題,python不支援尾遞迴,遞...
對遞迴的簡單理解
今天一小夥伴寫了乙個遞迴,echo可以輸出要取的值,return的卻總是null,寫了乙個簡單的測試復原一下問題。function test i echo i return i a test 30 var dump a 結果如下 261014182226 int 26 思路看上去很簡單,i 3就遞迴...