<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C語言函數(shù)遞歸

          共 1751字,需瀏覽 4分鐘

           ·

          2021-01-07 11:11

          前言

          上章節(jié)講到C語言的函數(shù),詳細內(nèi)容請參見上章節(jié)。本章節(jié)主要是給大家介紹下C語言函數(shù)中的難點函數(shù)遞歸。

          遞歸概念

          在C語言中,函數(shù)調(diào)用可以從main()函數(shù),其他函數(shù)或同一函數(shù)本身進行。遞歸函數(shù)定義如下:一個函數(shù)調(diào)用函數(shù)自身稱為遞歸函數(shù)。應該非常小心地使用遞歸函數(shù),因為當一個函數(shù)自己調(diào)用它進入無限循環(huán)時。當函數(shù)進入無限循環(huán)時,函數(shù)執(zhí)行永遠不會完成。我們應該定義退出函數(shù)調(diào)用的條件,以便遞歸函數(shù)終止。當一個函數(shù)被自己調(diào)用時,第一個調(diào)用仍在執(zhí)行中,直到調(diào)用最后一個調(diào)用。每次調(diào)用函數(shù)調(diào)用時,該函數(shù)都會將執(zhí)行控件返回到上一個函數(shù)調(diào)用。舉個栗子,你用你手中的鑰匙打開一扇門,結(jié)果卻發(fā)現(xiàn)前方還有一扇門,緊接著你又用鑰匙打開了這扇門,然后你又看到一扇門...但是當你開到某扇門時,發(fā)現(xiàn)前方是一堵墻無路可走了,你選擇原路返回——這就是遞歸,如下圖即使是遞歸。

          從階乘看遞歸

          階乘是基斯頓·卡曼(Christian Kramp,1760~1826)于 1808 年發(fā)明的運算符號,是數(shù)學術(shù)語。一個正整數(shù)的階乘factorial)是所有小于及等于該數(shù)的正整數(shù)的積,并且0的階乘為1。自然數(shù)n的階乘寫作n!。1808年,基斯頓·卡曼引進這個表示法。亦即n!=1×2×3×...×n。階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n

          在上面的示例程序中,factorial()函數(shù)調(diào)用是從main()函數(shù)啟動的,其值為3.在factorial()函數(shù)內(nèi),函數(shù)調(diào)用factorial(2),factorial(1)和factorial(0)被調(diào)用遞歸。在該程序執(zhí)行過程中,函數(shù)調(diào)用factorial(3)仍在執(zhí)行中,直到函數(shù)調(diào)用factorial(2),factorial(1)和factorial(0)的執(zhí)行完成。類似地,函數(shù)調(diào)用factorial(2)仍在執(zhí)行中,直到函數(shù)調(diào)用factorial(1)和factorial(0)的執(zhí)行完成。以相同的方式,函數(shù)調(diào)用factorial(1)保持執(zhí)行,直到函數(shù)調(diào)用factorial(0)的執(zhí)行完成。上述程序的完整執(zhí)行過程如下圖所示:


          遞歸函數(shù)的優(yōu)點是定義簡單,邏輯清晰。理論上,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰。使用遞歸函數(shù)需要注意防止棧溢出。在計算機中,函數(shù)調(diào)用是通過棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,每當進入一個函數(shù)調(diào)用,棧就會加一層棧幀,每當函數(shù)返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會導致棧溢出。可以試試factorial(1000)。

          解決遞歸調(diào)用棧溢出的方法是通過尾遞歸優(yōu)化,事實上尾遞歸和循環(huán)的效果是一樣的,所以,把循環(huán)看成是一種特殊的尾遞歸函數(shù)也是可以的。尾遞歸是指,在函數(shù)返回的時候,調(diào)用自身本身,并且,return語句不能包含表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調(diào)用多少次,都只占用一個棧幀,不會出現(xiàn)棧溢出的情況。

          可以看到,return fact_iter(n- 1, n* result)僅返回遞歸函數(shù)本身,n- 1和n* result在函數(shù)調(diào)用前就會被計算,不影響函數(shù)調(diào)用。尾遞歸調(diào)用時,如果做了優(yōu)化,棧不會增長,因此,無論多少次調(diào)用也不會導致棧溢出。

          尾言

          使用遞歸函數(shù)的優(yōu)點是邏輯簡單清晰,缺點是過深的調(diào)用會導致棧溢出。針對尾遞歸優(yōu)化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實上和循環(huán)是等價的,沒有循環(huán)語句的編程語言只能通過尾遞歸實現(xiàn)循環(huán)。標準的解釋器沒有針對尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問題。

          作業(yè):

          漢諾塔的移動可以用遞歸函數(shù)非常簡單地實現(xiàn)。

          請編寫move(n, a, b, c)函數(shù),它接收參數(shù)n,表示3個柱子A、B、C中第1個柱子A的盤子數(shù)量,然后打印出把所有盤子從A借助B移動到C的方法。

          駿馬是跑出來的,強兵是打出來的。駕馭命運的舵是奮斗。不抱有一絲幻想,不放棄一點機會,不停止一日前進腳步。



          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人无码视频成 | 热久久思思热 | 做爱福利导航 | 亚洲欧美性爱在线视频 | 韩国黄色一区二区三区 免费 |