遞迴與尾遞迴總結

2021-07-08 13:41:30 字數 2153 閱讀 1092

編者按:尾遞迴最大的好處就是不需要儲存當前函式的現場,在彙編級別即不需要call和set了

1、遞迴

關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件、遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進;當邊界條件滿足時,遞迴返回。用遞迴需要注意以下兩點:

(1) 遞迴就是在過程或函式裡呼叫自身。(2) 在使用遞迴策略時,必須有乙個明確的遞迴結束條件,稱為遞迴出口。

遞迴一般用於解決三類問題:

(1)資料的定義是按遞迴定義的。(fibonacci函式,n的階乘)

(2)問題解法按遞迴實現。(回溯)

(3)資料的結構形式是按遞迴定義的。(二叉樹的遍歷,圖的搜尋)

遞迴的缺點:

遞迴解題相對常用的演算法如普通迴圈等,執行效率較低。因此,應該盡量避免使用遞迴,除非沒有更好的演算法或者某種特定情況,遞迴更為適合的時候。

在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存,因此遞迴次數過多容易造成棧溢位。

用線性遞迴實現fibonacci函式,程式如下所示:

1

int fibonaccirecursive(intn)2

遞迴寫的**非常容易懂,完全是根據函式的條件進行選擇計算機步驟。例如現在要計算n=5時的值,遞迴呼叫過程如下圖所示:

2、尾遞迴

顧名思義,尾遞迴就是從最後開始計算, 每遞迴一次就算出相應的結果, 也就是說, 函式呼叫

出現在呼叫者函式的尾部, 因為是尾部, 所以根本沒有必要去儲存任何區域性變數

. 直接讓被呼叫的函式返回時越過呼叫者, 返回到呼叫者的呼叫者去。尾遞迴就是把當前的運算結果(或路徑)放在引數裡傳給下層函式

,深層函式所面對的不是越來越簡單的問題,而是越來越複雜的問題,因為引數裡帶有前面若干步的運算路徑。

尾遞迴是極其重要的,不用尾遞迴,函式的堆疊耗用難以估量,需要儲存很多中間函式的堆疊。比如f(n, sum) = f(n-1) + value(n) + sum; 會儲存n個函式呼叫堆疊,而使用尾遞迴f(n, sum) = f(n-1, sum+value(n)); 這樣則只保留後乙個函式堆疊即可,之前的可優化刪去。

採用尾遞迴實現fibonacci函式,程式如下所示:

1

int fibonaccitailrecursive(int n,int ret1,int

ret2)

2

例如現在要計算n=5時的值,尾遞迴呼叫過程如下圖所示:

從圖可以看出,為遞迴不需要向上返回了,但是需要引入而外的兩個空間來保持當前的結果。

為了更好的理解尾遞迴的應用,寫個程式進行練習。採用直接遞迴和尾遞迴的方法求解單鏈表的長度,c語言實現程式如下所示:

1 #include 2 #include 3

4 typedef struct

node

5node,*linklist;910

void initlinklist(linklist*head)

1117

18void insertnode(linklist* head,int

d)19

2526

//直接遞迴求鍊錶的長度

27int

getlengthrecursive(linklist head)

2833

//採用尾遞迴求鍊錶的長度,借助變數acc儲存當前鍊錶的長度,不斷的累加

34int getlengthtailrecursive(linklist head,int *acc)

3541

42void

printlinklist(linklist head)

4350 printf("

->null\n");

51}5253

intmain()

54

程式測試結果如下圖所示:

參考:

遞迴與尾遞迴總結

1 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接地呼叫自身,是為直接或間接遞迴。一般來說,遞迴需要有邊界條件 遞迴前進段和遞迴返回段。當邊界條件不滿足時,遞迴前進 當邊界條件滿足時,遞迴返回。用遞迴需要注意以下兩點 1 遞迴就是在過程或函式裡呼叫自身。2 在使用遞迴策略時...

演算法 遞迴與尾遞迴總結

前言 今天上網看帖子的時候,看到關於尾遞迴的應用 大腦中感覺這個詞好像在 見過,但是又想不起來具體是怎麼回事。如是乎,在網上搜了一下,頓時豁然開朗,知道尾遞迴是怎麼回事了。下面就遞迴與尾遞迴進行總結,以方便日後在工作中使用。1 遞迴 關於遞迴的概念,我們都不陌生。簡單的來說遞迴就是乙個函式直接或間接...

學習遞迴(總結)

學習遞迴 總結 遞迴是設計和描述演算法的一種有力的工具,由於它在複雜演算法的描述中被經常採用,為此在進一步介紹其他演算法設計方法之前先討論它。能採用遞迴描述的演算法通常有這樣的特徵 為求解規模為n的問題,設法將它分解成規模較小的問題,然後從這些小問題的解方便地構造出大問題的解,並且這些規模較小的問題...