從斐波那契數列開始了解遞迴和尾遞迴的區別

2021-08-21 12:55:11 字數 1768 閱讀 4686

遞迴函式是指一些會在函式內呼叫自己的函式,如果在遞迴函式中,遞迴呼叫返回的結果總被直接返回,則稱為尾部遞迴。尾部遞迴的函式有助將演算法轉化成函式程式語言,而且從編譯器角度來說,亦容易優化成為普通迴圈。這是因為從電腦的基本面來說,所有的迴圈都是利用重複移跳到**的開頭來實現的。如果有尾部歸遞,就只需要疊套乙個堆疊,因為電腦只需要將函式的引數改變再重新呼叫一次。利用尾部遞迴最主要的目的是要優化。

遞迴處理斐波那契數列,**如下:

#include "stdio.h"

#include "math.h"

int factorial(int n);

int main(void)

// 遞迴

int factorial(int n)

else

}

執行結果:

請輸入斐波那契數n:20

6765

process returned 0 (0x0) execution time : 3.502 s

press any key to continue.

尾遞迴處理斐波那契數列,**如下:
#include "stdio.h"

#include "math.h"

int factorial(int n);

int main(void)

int factorial_tail(int n,int acc1,int acc2)

else

return acc2;

}

執行結果:

請輸入斐波那契數n:20

6765

process returned 0 (0x0) execution time : 1.460 s

press any key to continue.

快了一倍多,再來看看尾遞迴的每一步是怎麼執行的:

int factorial_tail(int n,int acc1,int acc2)

else

}

執行結果:

請輸入斐波那契數n:10

factorial_tail(9, 1, 2)

factorial_tail(8, 2, 3)

factorial_tail(7, 3, 5)

factorial_tail(6, 5, 8)

factorial_tail(5, 8, 13)

factorial_tail(4, 13, 21)

factorial_tail(3, 21, 34)

factorial_tail(2, 34, 55)

factorial_tail(1, 55, 89)

55 process returned 0 (0x0) execution time : 1.393 s

press any key to continue.

原本樸素的遞迴產生的棧的層次像二叉樹一樣,以指數級增長,但是現在棧的層次卻像是陣列,變成線性增長了,實在是奇妙,總結起來也很簡單,原本棧是先擴充套件開,然後邊收攏邊計算結果,現在卻變成在呼叫自身的同時通過引數來計算。

小結:尾遞迴的本質是:將單次計算的結果快取起來,傳遞給下次呼叫,相當於自動累積。

為什麼尾遞迴也是遞迴,卻不會造成棧溢位呢?因為編譯器通常都會對尾遞迴進行優化。編譯器會發現根本沒有必要儲存棧資訊了,因而會在函式尾直接清空相關的棧。

斐波那契數列求解 尾遞迴

1.普通遞迴 這裡觀察f 4 的遞迴樹代替f 10 的遞迴樹 後者比較大,畫不下 使用遞迴求解的時候複雜度為t n t n 1 t n 2 t n t n 1 t n 2 t n t n 1 t n 2 觀察遞迴樹,發現降速最快的是最右邊每次減2,因此n 2 frac 2n 層以上的部分肯定是滿二叉...

斐波那契 尾遞迴

1 計算任意數n的階乘 5 5 4 3 2 1 8 8 7 6 5 4 3 2 1 遞迴函式通過兩個條件出發回的過程 1 當前函式徹底執行完畢的時候,觸發回的過程,回到上一層函式的呼叫處 2 當前函式遇到return 返回值的時,觸發回的過程,回到上一層函式的呼叫處 普通方法 n 5 total 1...

斐波那契 尾遞迴,DP

先看斐波拉契遞迴的樸素版本 int fib1 int n 這段 的意思是 第n個數等於前兩個數之和。但 f 1 1,f 0 0,這兩個特殊值作為遞迴出口。優化 尾遞迴 int fib wei int n int a,int b intmain 這段 明顯可讀性比樸素版本低,但優點在於將時間複雜度從o...