遞迴的原理,是利用函式本身的堆疊(stack)性質--後進先出(last in, first out,LIFO)來達成的。說得簡單一點,就是當某個函式呼叫另一個函式時,其會先執行完被呼叫的函式,才繼續執行自身的函式內容。
讓我們舉一個常見的例子來解釋:階乘(factorial)。
在數學上的定義中,對於一個非負整數 n,其階乘代表的是所有小於或等於 n 的正整數乘積,記作 n!。即 n! = 1 × 2 × 3 × ... × n。若我們規定 0! = 1,則可以將之改寫成:對於所有非負整數 n,(n + 1)! = (n + 1) × n!。
於是,我們便可以利用程式寫出計算階乘的遞迴函式。以下為其虛擬碼:
Function factorial(Integer n) If n = 0 then Return 1 Else Return n × factorial(n - 1) End
在這裡,我們相當於將原始的問題 n! 看作是 n × (n - 1)! 這個較小的問題。也就是得知 (n - 1)! 的值,就可以求得 n! 的解。同樣的,又可以將 (n - 1)! 看作是 (n - 1) × (n - 2)!、將 (n - 2)! 看作是 (n - 2) × (n - 3)!、......。
舉例來說,若是我們需要利用程式求出 6! 的值。則在我們呼叫 factorial(6) 時,為了得出結果,亦須求出 factorial(5) 的值。而為了得出 factorial(5) 的結果,我們亦須求出 factorial(4) 的值......。一直不斷遞迴下去,直到達到終止條件:n = 0 為止。
實際運作的結果,就如下圖所示意的(藍箭頭代表呼叫,紅箭頭代表回傳):
除此之外,遞迴還可以解決相當多其他的問題。例如斐波那契數列(fibonacci sequence)、老鼠走迷宮(mouse in a maze)、以及河內塔(tower of hanoi)等等,這裡我就不加贅述了。
雖然利用程式的遞迴解法較為直觀,但是不斷堆疊函式的結果,極有可能浪費了過多的記憶體空間。其實,遞迴的程式多半都能藉由迴圈的方式替代,只是程式也可能會因此變得複雜難懂。至於實際上要使用何者,就看你怎麼選擇囉。
7 回覆:
個人覺得遞迴非常難用= =尤其是到了很複雜的時候 連自己都不知道該怎麼做
比較起來 迴圈解似乎直觀(個人認為啦)而且效能高一點
一直都很好奇 像這樣子比較耗資源及時間的解法 在大型程式上會不會被使用呢?
另外 貓抓老鼠的程式我有看過囉 不過...總覺得好像比較接近DFS..找最快路徑是不是用Queue+陣列會比較好做呢?
這樣喔,我個人是認為遞迴通常較迴圈直覺。
在大型程式上,我想應該都會選擇較節省資源與時間的方式吧。
頂多就是,在某些關鍵點上於空間與時間上做出取捨。
貓抓老鼠,是指老鼠走迷宮嗎?
應用遞迴來找路徑,其實跟 DFS 本質上是相同的。
至於利用 Queue 來找,應該是 BFS 的方式吧?
這兩者各有適合使用的情況,也不能直接斷定何者較好。
我覺得fibonacci其實不算好例子,因為非遞迴寫法也很簡單,甚至比遞迴解更簡單直覺。以致於學習者常認為,我有好好的迴圈作法不做,何必來弄這個難搞的方法?
演算法中常常見到的 Devide&Conquer 式的思想,才是遞迴的精華,先把大問題切成小問題,然後從小問題集合成大問題的解,錮中核心就在遞迴關係式上。寫得出遞迴關係式,問題往往就迎刃而解了。
一點點小看法@_@"
其實我舉的例子是 factorial.....XD
一開始舉這個例子,是為了簡單介紹遞迴的想法
原因我身邊多數人都認為遞迴很難懂,故想以此來做個簡單的介紹
我認同你所說的,D&C 為遞迴精華的觀點
在文章中我也有提到這點,不過這個例子看來好像真的不太明顯 XD
總之,感謝你的意見囉:)
遞迴@@
那疊代的虛擬碼呢?
謝謝小參的教學,每一篇都非常直覺易懂!!
這個... gettoken是否..很像遞迴的觀念?
Public Function GetToken(new_txt As String, delimiter As String) As String
Static txt As String
Dim pos As Integer
' Save new text.
If new_txt <> "" Then txt = new_txt
pos = InStr(txt, delimiter)
If pos < 1 Then pos = Len(txt) + 1
GetToken = Left$(txt, pos - 1)
pos = Len(txt) - pos + 1 - Len(delimiter)
If pos < 1 Then
txt = ""
Else
txt = Right$(txt, pos)
End If
End Function
張貼留言