遞歸算法在計算機中的狀態變化

1、題目如下:

設有一個遞歸算法如下:
int X(int n){
	if(n<=3) 
		return 1;
	else
		return X(n-2)+X(n-4)+1;
}
則計算X(X(8))時需要計算X函數_____次

2、題目分析

首先這是一個遞歸算法,要計算X(X(8))執行X函數次數,必須從內到外;
先分析X(8)執行X函數的次數,進而得到X(8)的結果,再代入到外部X函數中繼續進行計算。

  • 數學分析

1. 先計算X(8)的值:

X(8)… … … … … … … … … … … … … … … … 此行調用了X函數1
= X(6) + X(4) + 1 … … … … … … … … … … 此行調用了X函數2
= X(4) + X(2) + 1 + X(2) + X(0) + 1 + 1 … 此行調用了X函數4
= X(2) + X(0) + 1 + 1 +1 + 1 + 1 + 1 + 1… 此行調用了X函數2
= 1 + 1 + 1 + 1 +1 + 1 + 1 + 1 + 1
= 9
所以內層函數X(8)計算結果爲9;共執行X函數9
進而X(X(8))就可以寫成X(9),然後求其執行X函數的次數

2. 再計算X(9)的值:

X(9)… … … … … … … … … … … … … … … … 此行調用了X函數1
= X(7) + X(5) + 1 … … … … … … … … … … 此行調用了X函數2
= X(5) + X(3) + 1 + X(3) + X(1) + 1 + 1 … 此行調用了X函數4
= X(3) + X(1) + 1 + 1 +1 + 1 + 1 + 1 + 1… 此行調用了X函數2
= 1 + 1 + 1 + 1 +1 + 1 + 1 + 1 + 1
= 9
可以看到X(9)執行X函數的次數也是9次;

根據數學元素可以算出`X(X(8))`執行X函數的總次數爲`18`次,函數返回結果爲`9`;
所以可以得出答案,則計算`X(X(8))`時需要計算X函數`9`次。

3、計算機程序是如何執行的呢?

計算機程序執行的傳參和計算狀態

根據上圖可以看到計算機在執行此程序是,函數調用(傳參)和函數返回(計算)時候的狀態,向下的箭頭表示函數調用(傳參)狀態,向上的箭頭表示函數返回(計算)狀態,也可以清晰的看到調用次數。
實際上上圖計算機程序執行就是一個完整的遞歸樹

4、此函數調用過程

調用前,系統完成:

  1. 將實參,返回地址等傳遞給被調用函數
  2. 爲被調用函數的局部變量分配存儲區
  3. 將控制轉移到被調用函數的入口

調用後,系統完成:

  1. 保存被調用函數的計算結果
  2. 釋放被調用函數的數據區
  3. 依照被調用函數保存的返回地址將控制轉移到調用函數

5、遞歸算法

遞歸算法(英語:recursion algorithm)在計算機科學中是指一種通過重複將問題分解爲同類的子問題而解決問題的方法。遞歸式方法可以被用於解決很多的計算機科學問題,因此它是計算機科學中十分重要的一個概念。絕大多數編程語言支持函數的自調用,在這些語言中函數可以通過調用自身來進行遞歸。計算理論可以證明遞歸的作用可以完全取代循環,因此在很多函數編程語言(如Scheme)中習慣用遞歸來實現循環。

能夠解決的問題:

  1. 數據的定義是按遞歸定義的。如Fibonacci函數。
  2. 問題解法按遞歸算法實現。如Hanoi問題。
  3. 數據的結構形式是按遞歸定義的。如二叉樹、廣義表等。

遞歸函數調用的實現

1、“層次”

主函數         0層
第1次調用      1層
第i次調用      i層

2、“遞歸工作棧”
3、“工作記錄” :實在參數,局部變量和返回地址

效率分析

  1. 時間效率

與遞歸樹的節點數成正比 :T(n) = O(2^n)

  1. 空間效率

與遞歸樹的深度成正比 : S(n) = O(n)

遞歸的優缺點

  • 優點 :結構清晰,程序易讀
  • 缺點 :每次調用要生成工作記錄,保存狀態信息,入棧;返回時要出棧,恢復狀態信息,時間開銷大

6、代碼實現

  1. 程序實現過程
    下面的程序可以清楚地看到函數執行的次數和函數調用是傳參的狀態

main.c

#include<stdio.h>
int count = 0;
int X(int n){
	count = count + 1;
	printf("count = %d  n = %d\n", count, n);
	if (n<=3) {
		return 1;
	}
	else {
		return X(n-2)+X(n-4)+1;
	}
}

int main(){
	X(X(8));
	printf("執行X函數次數爲%d",count);
	return 0;
}
  1. 程序運行結果
count = 1  n = 8
count = 2  n = 6
count = 3  n = 4
count = 4  n = 2
count = 5  n = 0
count = 6  n = 2
count = 7  n = 4
count = 8  n = 2
count = 9  n = 0
count = 10  n = 9
count = 11  n = 7
count = 12  n = 5
count = 13  n = 3
count = 14  n = 1
count = 15  n = 3
count = 16  n = 5
count = 17  n = 3
count = 18  n = 1
執行X函數次數爲18
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章