1. 程式人生 > 其它 >迭代和遞迴

迭代和遞迴

一.遞迴

所謂“遞迴”,就是“遞”+“歸”,“遞”就是層層遞進,“歸”則是歸納結果

可見,這是一個進出的關係,遞進去,歸出來。既然要歸出來,肯定需要有個結束條件,要不了就一直歸下去不出來了。

程式呼叫自身的程式設計技巧稱為遞迴( recursion)。遞迴演算法解題相對常用的演算法如普通迴圈等,執行效率較低。因此,應該儘量避免使用遞迴,除非沒有更好的演算法或者某種特定情況,遞迴更為適合的時候。

在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存。遞迴次數過多容易造成棧溢位等。

遞迴跟迴圈的區別

單看上面wiki的定義,貌似跟通常所說的無限死迴圈很像,他們的區別在哪?
遞迴是靜中有動,有去有回。
迴圈是動靜如一,有去無回。

舉個例子,給你一把鑰匙,你站在門前面,問你用這把鑰匙能開啟幾扇門。

遞迴:
1.你打開面前這扇門,看到屋裡面還有一扇門(這門可能跟前面開啟的門一樣大小(靜),也可能門小了些(動))
2.你走過去,發現手中的鑰匙還可以開啟它,你推開門,發現裡面還有一扇門,你繼續開啟,。。。
3.若干次之後,你打開面前一扇門,發現只有一間屋子,沒有門了。
4.你開始原路返回,每走回一間屋子,你數一次,走到入口的時候,你可以回答出你到底用這鑰匙開了幾扇門。

迴圈:
1.你打開面前這扇門,看到屋裡面還有一扇門,(這門可能跟前面開啟的門一樣大小(靜),也可能門小了些(動))
2.你走過去,發現手中的鑰匙還可以開啟它,你推開門,發現裡面還有一扇門,(前面門如果一樣,這門也是一樣,第二扇門如果相比第一扇門變小了
3.這扇門也比第二扇門變小了(動靜如一,要麼沒有變化,要麼同樣的變化)),你繼續開啟這扇門,。。。,一直這樣走下去。
4.入口處的人始終等不到你回去告訴他答案。

遞迴思想

遞迴就是有去(遞去)有回(歸來)

具體來說,為什麼可以”有去“?
這要求遞迴的問題需要是可以用同樣的解題思路來回答類似但略有不同的問題(上面例子中的那一把鑰匙可以開後面門上的鎖)。

為什麼可以”有回“?
這要求這些問題不斷從大到小,從近及遠的過程中,會有一個終點,一個臨界點,一個baseline,一個你到了那個點就不用再往更小,更遠的地方走下去的點,然後從那個點開始,原路返回到原點。

遞迴的基本思想是把規模大的問題轉化為規模小的相似的子問題來解決。在函式實現時,因為解決大問題的方法和解決小問題的方法往往是同一個方法,所以就產生了函式呼叫它自身的情況。另外這個解決問題的函式必須有明顯的結束條件,這樣就不會產生無限遞迴的情況了。

什麼時候需要用遞迴?

當有些問題的定義本身就是遞迴形式的時候,最是適合用遞迴來解決。

計算機專業的同學最最熟悉的莫過於”樹“的定義了[4,5]。還有一些定義,比如階乘,Fibonacci數列[6],等等。

用遞迴來解決這些問題,往往幾行程式碼就搞定了一些看起來相當”嚇人“的問題。 當然,遞迴的效能問題是另一回事,棧的分配,函式呼叫代價都是在具體工程實踐中要考慮的。 但現在只是討論遞迴思想的話,不妨先放下那些,欣賞下遞迴的美。

二.迭代

迭--反覆,輪流 代--代換,代替意思就是就是不停的代換的意思,迭代是重複反饋過程的活動,其目的通常是為了逼近所需目標或結果。

每一次對過程的重複稱為一次“迭代”,而每一次迭代得到的結果會作為下一次迭代的初始值。

對計算機特定程式中需要反覆執行的子程式*(一組指令),進行一次重複,即重複執行程式中的迴圈,直到滿足某條件為止,亦稱為迭代。常見有:迴圈語句(如for,foreach)、java中的Iterator(迭代器)

本文版權歸作者所有,歡迎轉載,請務必新增原文連結。