日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言递归算法

發布時間:2024/3/12 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言递归算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

遞歸

什么是遞歸?

遞歸的兩個必要條件?

遞歸的優缺點

遞歸求階乘

遞歸求斐波那契數

優化求階乘和斐波那契數

總結


遞歸

什么是遞歸?

所謂遞歸,我認為就是存在傳遞也存在歸還功能的一種算法,簡單點來說,就是一個函數直接或間接調用自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。特點:函數自己調用自己

遞歸的兩個必要條件?

  • 存在限制條件,當滿足這個限制條件的時候,遞歸便不再繼續。?
  • 每次遞歸調用之后越來越接近這個限制條件

遞歸的優缺點

優點:

  • 簡潔。只需要幾行代碼就能實現遞歸。
  • 在樹的前序,中序,后序遍歷算法中,遞歸的實現明顯要比循環簡單得多。

  • 缺點:

  • 遞歸由于是函數調用自身,而函數調用是有時間和空間的消耗的:每一次函數調用,都需要在內存棧中分配空間以保存參數、返回地址以及臨時變量,而往棧中壓入數據和彈出數據都需要時間。->效率
  • 遞歸中很多計算都是重復的,由于其本質是把一個問題分解成兩個或者多個小問題,多個小問題存在相互重疊的部分,則存在重復計算,如Fibonacci斐波那契數列的遞歸實現。->效率
  • 調用棧可能會溢出,其實每一次函數調用會在內存棧中分配空間,而每個進程的棧的容量是有限的,當調用的層次太多時,就會超出棧的容量,從而導致棧溢出。->性能

  • 下面從幾個遞歸的例題讓大家更清楚的理解遞歸算法!

    遞歸求階乘

    • 函數功能:設計factorial函數求第n階的階乘數。(不考慮溢出)
    • 遞歸部分:階乘的原公式是:n!=n*(n-1)*(n-2)...3*2*1,根據將大問題分解成小問題,我們把它轉換成這樣:n!=n*(n-1)!
    • 核心代碼:
    int factorial(int n) {if(n <= 1)// 0! = 1return 1;elsereturn n* factorial(n-1) }

    當n=5時 Factorial函數遞歸過程配圖如下:


    遞歸求斐波那契數

    普及一下,斐波那契數列(Fibonacci Sequence)又稱黃金分割數列,因數學家萊昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……

    • 函數功能:設計Fibonacci函數求第n個斐波那契數的值。(不考慮溢出)
    • 遞歸部分:F(n)=F(n-1)+F(n-2)(n>2,n∈N*,F[1]=1,F[2]=1),也就是一個數會等于前兩個數相加的結果。
    • 核心代碼:
    int fib(int n) {if(n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2) }

    當n=6時,Fibonacci函數遞歸過程配圖如下:


    從以上兩個例題我們不難看出有些問題

    • Factorial函數遞歸會隨著n的增加而使棧的空間變小,以至于棧溢出,程序崩潰。
    • Fibonacci函數遞歸會存在很多重復的計算,使得計算起來特別耗費時間。

    遞歸與棧的關系

    遞歸的過程就是出入棧的過程,在調試factorial函數的時候,如果你給的參數比較大,那就會報錯:Stack Overflow(棧溢出)這樣的信息。系統分配給程序的棧空間是有限的,但是如果出現了死循環,或者(死遞歸),這樣有可能導致一直開辟棧空間,最終產生棧空間耗盡的情況,這樣的現象我們稱為棧溢出。

    那如何優化解決上述的問題呢?

  • 將遞歸改寫成非遞歸。
  • 使用static對象替代nonstatic局部對象。在遞歸函數設計中,可以使用static對象替代nonstatic局部對象(即棧對象),這不僅可以減少每次遞歸調用和返回時產生和釋放nonstatic對象的開銷,而且static對象還可以保存遞歸調用的中間狀態,并且可為各個調用層所訪問。

  • 優化求階乘和斐波那契數

    • 非遞歸的核心代碼:
    //求n的階乘(非遞歸) int factorial(int n) {int result = 1;while(n > 1){result *= n;n -= 1;}return result; } //求第n個斐波那契數(非遞歸) int fib(int n) {int result;int pre_result;int next_older_result;result = pre_result = 1;while(n > 2){n -= 1;next_older_result = pre_result;pre_result = result;result = pre_result + next_older_result;}return result; }

    總結

  • 解決遞歸問題的主要思想是分治思想,即我們在遞歸時要盡量將問題的規模縮小。
  • 許多問題是以遞歸的形式進行解釋的,這只是因為它比非遞歸的形式更為清晰。
  • 但是這些問題的迭代實現往往比遞歸實現的效率更高,雖然代碼的可讀性稍微差些。
  • 當一個問題相當復雜,難以用迭代實現時,此時遞歸實現的簡潔性便可以補償它所帶來的運行時開銷

  • 看到這里你應該對于遞歸有了很深的理解吧!遞歸的學習是一個漫長的過程,畢竟大師 L. Peter Deutsch 說過:To Iterate is Human, to Recurse, Divine.中文譯為:人理解迭代,神理解遞歸。下篇我將會帶領大家研究幾個經典的遞歸問題。

  • 漢諾塔問題
  • 青蛙跳臺階問題
  • 如有補充或存在問題請在評論區留言喲~

    總結

    以上是生活随笔為你收集整理的C语言递归算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。