In order to understand recursion, one must first understand recursion.
To Iterate is Human, to Recurse, Divine.
遞迴的定義
子程式或者函式直接或者間接地呼叫自身。 遞迴是一種描述問題和解決問題的基本方法,相比(迴圈)之下遞迴寫出的程式碼可讀性更好,不過效能上並沒有優勢。此外,很多演算法的實現都離不開遞迴。
遞去歸來,遞是描述問題,歸時解決問題。
//例如A()函式內部呼叫了自己,叫做
//直接遞迴呼叫
function A(){
A();
}
//間接遞迴呼叫
function B(){
C();
}
function C(){
B();
}
//尾遞迴
function A(){
return A()
//作為return返回時呼叫,稱為尾遞迴
}
複製程式碼
遞迴的基本結構:
- 遞迴項&遞迴關係 (Recursive Case) 描述大問題如何分解為小問題,也稱為遞迴體
- 遞迴邊界條件(Base Case) 停止遞迴的條件,也稱為遞迴出口
// 虛擬碼
function recurtion(sth){
if(stopRecurtion === true){ //base case
return
}else{ //recurtion case
sth=expression //與子問題的遞迴關係
recurtion(sth) //呼叫自身
}
}
recurtion(sth)
複製程式碼
遞迴呼叫棧 The Call Stack
也稱為遞迴工作棧,層層向下遞迴,返回次序正好(與呼叫次序)相反
即遞迴中的每個子函式的呼叫是放入一個呼叫棧來執行,後進先出,所以遞迴到最深的子問題時開始逐層向上返回。
遞迴的一些簡單應用
- 階乘
- 遞迴演算法
- 非遞迴演算法
- 斐波那契豎列求解
- 遞迴演算法
- 非遞迴演算法
- 迴文串
- 遞迴演算法
- 非遞迴演算法
小結
應用遞迴解決的思路:
- 找到最小子問題
- 找到遞迴關係,即如何從頂層到達下一層的條件(關係)
- 寫出最小子問題的解決過程,在恰當的時候呼叫自己(實現遞迴關係)
- 遞的分析可以將問題關係描述清楚,歸的分析也是難點,是解決問題的關鍵
- 理解遞迴的執行棧可以幫助理清楚歸的過程
參考