一.遞歸
所謂“遞歸”,就是“遞”+“歸”,“遞”就是層層遞進,“歸”則是歸納結果
可見,這是一個進出的關系,遞進去,歸出來。既然要歸出來,肯定需要有個結束條件,要不了就一直歸下去不出來了。
程序調用自身的編程技巧稱為遞歸( recursion)。遞歸算法解題相對常用的算法如普通循環等,運行效率較低。因此,應該盡量避免使用遞歸,除非沒有更好的算法或者某種特定情況,遞歸更為適合的時候。
在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等。
遞歸跟循環的區別
單看上面wiki的定義,貌似跟通常所說的無限死循環很像,他們的區別在哪?
遞歸是靜中有動,有去有回。
循環是動靜如一,有去無回。
舉個例子,給你一把鑰匙,你站在門前面,問你用這把鑰匙能打開幾扇門。
遞歸:
1.你打開面前這扇門,看到屋里面還有一扇門(這門可能跟前面打開的門一樣大小(靜),也可能門小了些(動))
2.你走過去,發現手中的鑰匙還可以打開它,你推開門,發現里面還有一扇門,你繼續打開,。。。
3.若干次之后,你打開面前一扇門,發現只有一間屋子,沒有門了。
4.你開始原路返回,每走回一間屋子,你數一次,走到入口的時候,你可以回答出你到底用這鑰匙開了幾扇門。
循環:
1.你打開面前這扇門,看到屋里面還有一扇門,(這門可能跟前面打開的門一樣大小(靜),也可能門小了些(動))
2.你走過去,發現手中的鑰匙還可以打開它,你推開門,發現里面還有一扇門,(前面門如果一樣,這門也是一樣,第二扇門如果相比第一扇門變小了
3.這扇門也比第二扇門變小了(動靜如一,要么沒有變化,要么同樣的變化)),你繼續打開這扇門,。。。,一直這樣走下去。
4.入口處的人始終等不到你回去告訴他答案。
遞歸思想
遞歸就是有去(遞去)有回(歸來)
具體來說,為什么可以”有去“?
這要求遞歸的問題需要是可以用同樣的解題思路來回答類似但略有不同的問題(上面例子中的那一把鑰匙可以開后面門上的鎖)。
為什么可以”有回“?
這要求這些問題不斷從大到小,從近及遠的過程中,會有一個終點,一個臨界點,一個baseline,一個你到了那個點就不用再往更小,更遠的地方走下去的點,然后從那個點開始,原路返回到原點。
遞歸的基本思想是把規模大的問題轉化為規模小的相似的子問題來解決。在函數實現時,因為解決大問題的方法和解決小問題的方法往往是同一個方法,所以就產生了函數調用它自身的情況。另外這個解決問題的函數必須有明顯的結束條件,這樣就不會產生無限遞歸的情況了。
什么時候需要用遞歸?
當有些問題的定義本身就是遞歸形式的時候,最是適合用遞歸來解決。
計算機專業的同學最最熟悉的莫過於”樹“的定義了[4,5]。還有一些定義,比如階乘,Fibonacci數列[6],等等。
用遞歸來解決這些問題,往往幾行代碼就搞定了一些看起來相當”嚇人“的問題。 當然,遞歸的性能問題是另一回事,棧的分配,函數調用代價都是在具體工程實踐中要考慮的。 但現在只是討論遞歸思想的話,不妨先放下那些,欣賞下遞歸的美。
二.迭代
迭--反復,輪流 代--代換,代替意思就是就是不停的代換的意思,迭代是重復反饋過程的活動,其目的通常是為了逼近所需目標或結果。
每一次對過程的重復稱為一次“迭代”,而每一次迭代得到的結果會作為下一次迭代的初始值。
對計算機特定程序中需要反復執行的子程序*(一組指令),進行一次重復,即重復執行程序中的循環,直到滿足某條件為止,亦稱為迭代。常見有:循環語句(如for,foreach)、java中的Iterator(迭代器)