文章來源:http://blog.seclibs.com/算法之遞歸/算法
遞歸是一種應用很是普遍的算法,在不少的數據結構和算法的編碼中都會用到,理解遞歸是很是重要的。數據結構
遞歸在平時的生活中也是很是經常使用的,當你排隊的時候須要知道本身排在第幾個位置,而前面的人又比較多,你不能本身數出來,就能夠詢問你前一我的他的位置,在他的位置基礎上加一即是你的位置,那若是他也不知道他的位置呢,就能夠用一樣的方法,繼續向前詢問,直到第一我的,第一我的就不用往前問了,他直到本身是第一個,這個過程就是一個遞歸的過程。數據結構和算法
去問的時候叫作「遞」,返回來的時候叫作「歸」,假設本身是第n排,求本身位置的函數爲f(n),f(n-1)就是前一我的的位置,咱們的位置就是f(n-1)+1,一樣前一我的的位置也能夠用這個公式來計算, 直到第一我的f(1)=1,這一整套流程即是遞歸的實際利用,編寫成代碼以下函數
在編寫遞歸代碼的時候,有兩點必要的條件:編碼
若是結構不一樣,那就不能構造遞歸了;若是不存在終止條件的話,將會無限循環,看上面的那個例子,它的終止條件就是執行到第一我的的時候,開始日後返回。blog
遞歸就這樣完成了,上面這個例子是隻有一個遞歸調用的分支,仍是比較好理解的,若是有多個遞歸分支的話,單純靠人腦是很難理解清楚的,計算機比較適合作重複的工做,咱們若是一環一環往遞歸裏走的話,很快就迷糊了,惟一的方法就是本身屏蔽掉其中細節,只把握好第一個遞歸公式的構造和終止條件的判斷,就能更好的理解清楚遞歸了。遞歸
假若有n階臺階,能夠每次走一個臺階或兩個臺階,請問走完n階樓梯有多少種走法?內存
舉幾個例子,就能夠很明顯的發現,從第三層開始,每一層都是前兩層的次數相加,因此咱們就能夠獲得公式f(n) = f(n-1)+f(n-2) ,經過舉例子是最容易理解的一個方式,實際上去理解的方法有不少種,能夠本身去嘗試,你能夠用遞歸的想法去一層層跑一下,就會發現總體的困難程度是很是大的。文檔
因此將其轉換爲代碼就以下圖所示get
在寫遞歸代碼的時候,還須要注意兩個問題:
先說堆棧溢出,在函數調用時,會使用棧來保存臨時變量,每進行一次函數調用,就會將臨時變量封裝後壓入內存棧,這個棧的大小是由系統來決定的,若是遞歸太深,壓入棧中的數據是很是多的,就會有堆棧溢出的風險;解決辦法就是在遞歸函數中加入一個判斷條件,來判斷遞歸的深度,若是達到了某一個值,就直接返回報錯。
另外一個就是重複計算,當咱們在計算f(5)的時候會計算f(4)和f(3),在計算f(4)的時候還須要計算f(3),f(3)就被重複計算了,爲了不重複計算,能夠經過數據結構來記錄已經計算過的值,在計算前先進行判斷,若是計算過就直接將值返回。
爲了不這些狀況,也能夠將遞歸代碼改成迭代循環的非遞歸方式,就是使用循環的方式來進行處理。
參考文檔
極客時間-數據結構與算法之美
文章首發公衆號和我的博客
公衆號:無意的夢囈(wuxinmengyi)