java斐波那切数列_Java中的递归方法
遞歸算法
1.遞歸算法
遞歸在計算機科學中也稱為遞歸算法。一些問題在分解的時候會有這樣的現象:解決該問題的過程是由重復的相似子過程組成,類似這樣的問題我們都可以通過遞歸算法進行解決。在計算機語言中,遞歸算法的實現靠函數的自我調用來完成,我們所見到的大多數高級編程語言都支持這樣的做法。
遞歸算法通常有兩種方式實現——普通遞歸和尾遞歸。遞歸方法簡單的來說就是方法的內部再次調用自身,遞歸方法會嵌套的參與運算。這樣每一個遞歸方法都要分配一個函數堆棧進行操作,這就是普通遞歸。普通遞歸對內存的消耗是非常大的。
另一種遞歸方式被稱為尾遞歸,尾遞歸對普通遞歸進行了優化。如果使用尾遞歸,需要將遞歸方式進行特殊的設計,它需要將遞歸方法在return語句后進行單獨調用(即尾調用)。當采用尾遞歸的時候,一些編程語言會進行優化,將所有嵌套的遞歸方法放在同一個函數堆棧中進行,效率非???。作為一名Java程序員,如果你無法將遞歸方法設計成尾遞歸的模式也沒有任何問題,因為Java并沒有對尾遞歸進行優化 ,Java對內存的優化是依賴于回收機制。但是如果你是一名C程序員,就需要對尾遞歸的寫法進行掌握了。
遞歸算法的優缺點是非常明顯,算法實現簡單、可讀性強是遞歸算法的優點所在。缺點也同樣明顯,遞歸算法會占用大量內存空間,如果遞歸深度過大,容易發生內存相關問題。所以在遞歸算法中,有這樣一句話:不用遞歸累死,濫用遞歸慢死。如何合理的使用遞歸算法,是遞歸使用的關鍵問題。
2.怎么使用遞歸
在設計遞歸算法的時候,一定要注意兩點:1、設計出等價的遞歸公式。這一點需要我們擁有一些數學基礎以及抽象概括能力,能夠在復雜的運行過程中,抽象出等價的函數關系。
2、遞歸退出的條件。這一點尤為重要,如果遞歸方法沒有結束條件,就如同死循環一樣,讓內存和CPU直接"撐爆"。常見的遞歸練習方法有斐波那契數列和漢諾塔移動算法。
2.1 斐波那契數列(Fibonacci sequence)
斐波那契數列是經典的遞歸算法應用,它是一組有規律數列:"1,1,2,3,5,8,13……",當我們要獲取數列中第n位的數字時,可以總結如下公式:
當n=1或者2時,有f(n)=1,當>=3時,有f(n)=f(n-1)+f(n-2)
下面我們要設計一個方法,輸出數列的前n位的信息,n通過整型參數控制。如果我們需要一個完整的數列,就需要創建一個數列容器,將數列中的每一位數字依次計算出來,并保存到容器中,最后按照順序從容器中輸出數列(如下列Java示例):
使用數組保存斐波那契數列
采用上面的做法好處非常明顯,它能夠記錄每一位數列的值。當我們需要獲取整個數列的時候,這樣的方式是可取的。在一些時候,我們只想獲取其中一位的數值,我們就不需要記錄數列,這個時候使用遞歸的方式就非常方便(如下Java示例所示):
采用上述代碼,可以直接獲取到數列中第n位的數值。我們可以發現,使用遞歸的方式讓代碼更簡潔、閱讀起來更友好。下面我們創建兩個測試方法,對上述兩種方式進行測試:
運行結果:
2.2 漢諾塔(Hanoi)
漢諾塔是一種有趣的益智游戲,很多人在兒時都玩過這種類似的玩具(如下圖所示):
漢諾塔
漢諾塔的移動規則是將所有圓盤從A柱移動到C柱上,并保持上小、下大的有序順序擺放。在移動的過程中,也需要保持這個規則。例如上圖的三層漢諾塔,我們在移動的時候有如下步驟(如下圖所示):
三層漢諾塔移動步驟
如果有多個盤子,我們設盤子總數為n,我們可以分為兩部分解決,一部分是上面的n-1個盤子,它們作為一個整體,另一部分是最下面的盤子n。它們移動可以分為三步:
1.將第一部分的n-1個盤子的作為一個整體,從A移動到B柱上,C柱過度。
2.接著將第n個盤子從A柱移動到C柱上。
3.再將n-1個盤子的整體從B柱移動到C柱上,A柱過度(移動規律如下圖所示)。
N個盤子移動時的規律總結
用代碼實現的時候,我們就可以利用遞歸的方式進行移動。下面代碼中,我們為了觀察移動過程中,各柱子上盤子的變化情況,我們用隊列來模擬柱子(實現代碼如下所示):
運行結果:
3.遞歸對循環的替代
在程序開發過程中,很多循環方法都可以使用遞歸來完成,例如數字的累加和階層的計算(如下面代碼所示)。
運行結果:
在上述示例代碼中,我們用遞歸和非遞歸兩種方式解決了累加、階乘的循環問題。除此之外,在一些數據結構算法中,遞歸的使用也非常多,比如二叉樹的遍歷、排序等。在下面的示例中,我們使用遞歸的方法進行冒泡排序。
示例運行效果:
傳統的冒泡排序需要借助雙層循環進行排序交換。如果使用遞歸的方式,可以減少一層循環。在實際的排序中,我們是不推薦使用遞歸進行排序的,上述示例僅作為遞歸算法的一種思考。
總結
以上是生活随笔為你收集整理的java斐波那切数列_Java中的递归方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 维埃克斯与沙林的区别?
- 下一篇: java美元兑换,(Java实现) 美元