關於遞歸的一些思考

說到遞歸,咱們張嘴就能說出來是什麼?本身調用本身。官方點說就是一個函數用它本身來定義時就是遞歸。
有時候不少的數學問題或者生活中的問題均可以使用計算機程序來解決,把這些問題統計起來,找出他們之間的規律,得出一個計算公式,用程序來計算這個公式得出結果。夢想老是美好的,有時候咱們得出的公式有些是以不太標準的形式定義的。 css

例如斐波那契數列,經過分析咱們獲得一個公式,它知足:算法

F(0)=0  
                                F(1)=1
                                F(2)=1

                        F(n)=F(n-1)+F(n-2)(n>=2)

在上面的公式定義中咱們發現F(0)=0,F(1)=1,F(2)=1
利用遞歸咱們能夠很方便的獲得解決這個問題的方法,程序以下:markdown

public int getFib(int n) {
        if (n < 0) {
            return -1;
        } else if (n == 0) {
            return 0;
        } else if (n == 1 || n == 2) {
            return 1;
        } else {
            return getFib(n - 1) + getFib(n - 2);
        }
    }

上面的程序中兩個else if用於處理基準狀況,何爲基準狀況?就是函數的值不須要遞歸計算直接能夠得出的結果。一個遞歸函數必須有基準狀況(不須要遞歸計算就能夠獲得的結果),沒有基準狀況的遞歸方法沒有意義。
試着想想:咱們如今要利用上面的程序計算出F(3)的結果是多少?咱們發現若是要算F(3)就要知道F(2)和F(1)的值,咱們發現F(2)和F(1)的值已經知道了,那麼F(3)的結果很容易獲得。咱們先忘記上面的狀況,假如如今咱們要計算F(5),根據公式計算F(5)就要知道F(4)和F(3),可是F(4)和F(3)咱們不知道,可是能夠根據公式算出來,F(4)=F(3)加上F(2),F(3)=F(2)加上F(1),綜上所述之後的每個結果都是根據咱們已知的結果算出來的
在上面的程序中兩個else if給出了基準因此咱們後面的遞歸計算才能夠獲得。
上面的推倒結果的過程能夠發現遞歸就是一個循環推理的過程。
仍是這個基準的問題,求結果當咱們想要求F(1)的時候,若是沒有基準,求F(1)就要知道F(0)和F(-1),而後F(0)又要依賴F(-1)和F(-2),這樣一直向下計算,永遠不能算出結果,顯然這是一個錯誤的程序,這樣的結果就是計算機的資源所有都在計算這些沒有意義的計算,包括跟蹤掛起的函數調用以及他們的變量記錄工做都要計算機來完成。因此咱們在方法的最開始規定了參數不能小於0。 數據結構

前面的論述基本上討論了遞歸的兩個基本準則:
* 基準準則:就像一個開口,不用遞歸就能夠獲得的結果
* 不斷推動:須要遞歸求的計算,遞歸的方向老是朝着基準的方向推動 函數

書上有一個很好的例子助於理解,遇到一個不認識的詞語咱們要查字典,咱們根據下面的解釋理解這個詞語的意思,可是這段解釋中咱們又遇到了不認識的詞語,咱們又要接着查,就這樣一直查,直到咱們找到了一處咱們理解的詞語(就是上面說的基準)以前全部的也就理解了。這個查詢過程也就結束了。 spa

在設計遞歸函數的時候咱們假設全部的遞歸都能運行。當遞歸程序運行起來想要追蹤具體的調用關係是很困難的。
記住要有基準,每次遞歸朝着基準前進 設計


這篇文章根據《數據結構與算法分析》寫出,有書上的,也有個人理解,初讀這本書感受真的不同,字多,書上好多的知識解釋的很詳細,建議認真閱讀!作筆記!我從前對遞歸的理解就是一句話,總結了以後原來遞歸的知識能夠有這麼多。code

相關文章
相關標籤/搜索