1. 程式人生 > >C語言基礎 遞迴的用法及示例

C語言基礎 遞迴的用法及示例

---------------start reading----------------

前言 遞迴在數學證明中經常使用,其意就是不停的套用同一模板逐漸歸納出最後的結果,用通俗的話來說就是自己呼叫自己。

遞迴呼叫需要注意三個問題

  1. 縮小問題規模
  2. 邊界條件
  3. 返回段

我們來看看遞迴的入門題 有五個人年齡不等 第五個人說,我比第四個人大兩歲; 第四個人說,我比第三個人大兩歲; 第三個人說,我比第二個人大兩歲; 第二個人說,我比第一個人大兩歲;

在以前我們可以用迴圈來實現,功能程式碼如下

int Age1(int n)//O(n),O(1)
{
	int age = 10;
	for(int i=1;i<n;i++)
	{
		age += 2;
	}
	return age;
}

現在我們來用遞迴實現,功能函式如下

int Age(int n)//O(n),O(n)
{
	int tmp;
	if(n == 1)
		tmp = 10;
	else
		tmp = Age(n-1) + 2;
	return tmp;
}

遞迴實現的思路其實是這樣的 想要知道第五個人的年齡,就要先知道第四個人的年齡; 想要知道第四個人的年齡,就要先知道第三個人的年齡; 想要知道第三個人的年齡,就要先知道第二個人的年齡; 想要知道第二個人的年齡,就要先知道第一個人的年齡。 知道了第一個人的年齡就可以算出第二個人的年齡,進而算出第三個,第四個,最終得到第五個人的年齡

實現的物理模型如圖

在這裡插入圖片描述

遞迴就是通過不停的壓棧再出棧來實現問題規模縮小。有時候遞迴很方便,但是,遞迴也有很大的缺點,下面就讓遞迴和迴圈進行一下比較,你就知道遞迴的弊處了

如上題所示程式碼 迴圈 時間複雜度:O(n)

空間複雜度:定義了變數age,i,O(2)

遞迴 時間複雜度:O(n)

空間複雜度:由於遞迴沒有找到值就不會返回,所以遞迴進行時會不停的壓棧,空間複雜度為O(n),空間使用率小

綜上所述 遞迴雖然同迴圈的時間複雜度一樣,但在空間利用率上卻大大的跟不上。在windos中棧的空間只有1M,一個字元=兩個位元組如果資料稍微一大便會使程式崩潰。

接下來讓我們來用遞迴寫一寫斐波那契數列的功能函式

int Fibno(int n)
{
	if(n==1 || n==2)
		return 1;
	else
		return Fibno(n-1)+Fibno(n-2);
}

經過除錯,資料上40就很難調試出來,因為他用了很大的空間

但是也有適合使用遞迴的例子 漢諾塔問題,如何用最少的次數將三個圓環一道另一根柱子上且保持順序不變 在這裡插入圖片描述


int g_count = 0;
void Move(char x,char y)
{
	g_count++;
	printf("%c->%c\n",x,y);
}

void Hanoi(int n,char a,char b,char c)
{
	if(n == 1)
	{
		Move(a,c);
	}
	else
	{
		Hanoi(n-1,a,c,b);//
		Move(a,c);
		Hanoi(n-1,b,a,c);
	}
}

int main()
{
	Hanoi(5,'A','B','C');
	printf("%d\n",g_count);
}
漢諾塔移動過程就可以用遞迴來實現,方便理解,而且在實際操作中也不會有太多的空間浪費,漢諾塔是最適合用遞迴的例子


---------------end---------------