可能存在无限递归_你为什么学不会递归?读完这篇文章轻松理解递归算法
對于很多編程初學(xué)者來說,遞歸算法是學(xué)習(xí)語言的最大障礙之一。很多人也是半懂不懂,結(jié)果學(xué)到很深的境地也會因為自己基礎(chǔ)不好,導(dǎo)致發(fā)展太慢。
可能也有一大部分人知道遞歸,也能看的懂遞歸,但在實際做題過程中,卻不知道怎么使用。今天,我們就來說一說遞歸算法的使用。
什么是遞歸
遞歸,在數(shù)學(xué)與計算機(jī)科學(xué)中,是指在函數(shù)的定義中使用函數(shù)自身的方法。也就是說,遞歸算法是一種直接或者間接調(diào)用自身函數(shù)或者方法的算法。
通俗來說,遞歸算法的實質(zhì)是把問題分解成規(guī)??s小的同類問題的子問題,然后遞歸調(diào)用方法來表示問題的解。
遞歸的基本原理
第一:每一級的函數(shù)調(diào)用都有自己的變量。
第二:每一次函數(shù)調(diào)用都會有一次返回。
第三:遞歸函數(shù)中,位于遞歸調(diào)用前的語句和各級被調(diào)用函數(shù)具有相同的執(zhí)行順序。
第四:遞歸函數(shù)中,位于遞歸調(diào)用后的語句的執(zhí)行順序和各個被調(diào)用函數(shù)的順序相反。
第五:雖然每一級遞歸都有自己的變量,但是函數(shù)代碼并不會得到復(fù)制。
遞歸的優(yōu)缺點
優(yōu)點 | 缺點 |
●實現(xiàn)簡單 ●可讀性好 | ●遞歸調(diào)用,占用空間大 ●遞歸太深,易發(fā)生棧溢出 ●可能存在重復(fù)計算 |
遞歸的三大要素
第一要素:明確你這個函數(shù)想要干什么。先不管函數(shù)里面的代碼什么,而是要先明白,你這個函數(shù)的功能是什么,要完成什么樣的一件事。
第二要素:尋找遞歸結(jié)束條件。我們需要找出當(dāng)參數(shù)為啥時,遞歸結(jié)束,之后直接把結(jié)果返回,請注意,這個時候我們必須能根據(jù)這個參數(shù)的值,能夠直接知道函數(shù)的結(jié)果是什么。
第三要素:找出函數(shù)的等價關(guān)系式。我們要不斷縮小參數(shù)的范圍,縮小之后,我們可以通過一些輔助的變量或者操作,使原函數(shù)的結(jié)果不變。
遞歸的過程
具體地說,如果遞歸函數(shù)調(diào)用自己,則被調(diào)用的函數(shù)也將調(diào)用自己,這將無限循環(huán)下去,除非代碼中包含終止調(diào)用鏈的內(nèi)容。通常的方法將遞歸調(diào)用放在if語句中。例如,void類型的遞歸函數(shù)recurs()的代碼如下:
用文字再現(xiàn)這段代碼塊的內(nèi)容:
只要if語句為true,每個recurs()調(diào)用都將執(zhí)行statement1,然后再調(diào)用recurs(),而不會執(zhí)行statements2?。當(dāng)前調(diào)用結(jié)束后,程序控制權(quán)將返回給調(diào)用它的recurs(),而該recurs()將執(zhí)行其statements2部分,然后結(jié)束,并將控制權(quán)返回給前一個調(diào)用,依次類推。
遞歸的使用
遞歸的強(qiáng)大之處在于它允許用戶用有限的語句描述無限的對象。因此,在計算機(jī)科學(xué)中,遞歸可以被用來描述無限步的運算,盡管描述運算的程序是有限的。 這一點是循環(huán)不太容易做到的。
編寫正確的遞歸算法,一定要有 ”歸“ 的步驟,也就是說遞歸算法,在分解問題到不能再分解的步驟時,要讓遞歸有退出的條件,否則就會陷入死循環(huán),最終導(dǎo)致內(nèi)存不足引發(fā)棧溢出異常。
下面,我們通過兩個例子來學(xué)習(xí)一下,遞歸的使用:
例一:遞歸求階乘
例二:遞歸求斐波那契數(shù)列
從上面的步驟我們可以清晰的看到遞歸算法的第一步是分治,把復(fù)雜的大的問題,給拆分成一個一個小問題,直到不能再拆解,通過退出條件retrun,然后再從最小的問題開始解決,只到所有的子問題解決完畢,那么最終的大問題就迎刃而解。
遞歸的優(yōu)化方法
遞歸問題中想到思路本身不非常難,真正的難點在于如何優(yōu)化。
1、考慮是否重復(fù)計算
如果你使用遞歸的時候不進(jìn)行優(yōu)化,是有非常非常非常多的子問題被重復(fù)計算的。因此,使用遞歸的時候,必要須要考慮有沒有重復(fù)計算,如果重復(fù)計算了,一定要把計算過的狀態(tài)保存起來。
2、考慮尾遞歸
對于遞歸的問題,我們一般都是從上往下遞歸的,直到遞歸到最底,再一層一層著把值返回。
不過,有時候當(dāng) n 比較大的時候,例如當(dāng) n = 10000 時,那么必須要往下遞歸10000層直到 n <=1 才將結(jié)果慢慢返回,如果n太大的話,可能??臻g會不夠用。這個時候,就可以用尾遞歸優(yōu)化來解決。
顧名思義,尾遞歸就是從最后開始計算, 每遞歸一次就算出相應(yīng)的結(jié)果, 也就是說, 函數(shù)調(diào)用出現(xiàn)在調(diào)用者函數(shù)的尾部, 因為是尾部, 所以根本沒有必要去保存任何局部變量。直接讓被調(diào)用的函數(shù)返回時越過調(diào)用者, 返回到調(diào)用者的調(diào)用者去。
有的人剛接觸算法的時候,一直都懼怕遞歸,也很少或者說幾乎就不寫遞歸的代碼。但其實學(xué)習(xí)了以后,發(fā)現(xiàn)遞歸還是挺可愛的。就像在數(shù)學(xué)找一組數(shù)字的規(guī)律一樣,可以鍛煉我們的思維。希望這篇文章,能額昂你有所收獲。
相關(guān)鏈接:
幾種快速優(yōu)化MongoDB的方法,從此優(yōu)化不再難!
4種網(wǎng)頁設(shè)計技巧:圖文搭配,網(wǎng)頁不累!
巧用這10條MySQL技巧,事半功倍!
學(xué)會這8個Mybatis使用技巧,讓你省去沒必要的麻煩
點擊文末“”咨詢,免費來云和試聽課程——UI視覺交互全科班、Python人工智能高薪班、JAVA大數(shù)據(jù)企業(yè)直通班、HTML5全棧精英班、Unity虛擬現(xiàn)實大師班,座位有限,先搶先得!
總結(jié)
以上是生活随笔為你收集整理的可能存在无限递归_你为什么学不会递归?读完这篇文章轻松理解递归算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: adaptivitypara设置选0还是
- 下一篇: spark消费kafka产生数据堆积怎么