關於遞歸循環的總結(包含題目解析與思路)

C語言函數————遞歸(曾經困擾我很久的問題)
相信大家在一開始學習函數這一章節的時候,像我這樣的白癡腦袋曾經被遞歸這一算法思想困擾了很久。
所以這樣一篇博客早已是大一上學期剛學完遞歸後的我想總結的小節,這不剛放寒假嘛,趕緊抓住這一時機,寫下了這樣一篇博客~
希望大家看完發現錯誤後能即使留言批評與糾正。


首先先介紹一下遞歸
遞歸,顧名思義,就是套娃(doge)。所以剛開始作爲剛接觸語言學習的我來說,我就純把遞歸理解爲循環了,因爲都是對代碼的反覆使用。雖說這樣理解好像沒啥很大的毛病,因爲可以使用循環的地方通常都可以使用遞歸,但是深入瞭解過後還是能發現它們的區別:
1(個人覺得最大):遞歸的規模小,很大程度上受到棧上的限制
循環規模大,基本上不會受限制


2 :遞歸總是將問題從大到小放縮,所以限制條件也即(1==n)
循環則不然,既可以從大到小,也可以從小到大放縮,條件都是我們自己設定

還有一些比較深入的問題由於博主能力有限也總結不出來~…
總之它們兩者的不同也就順然的引出它們兩者的優缺點:
遞歸:代碼簡單易懂,但是效率低下(例子的話,可以看下面“斐波那契數列的”的解決)
循環:效率高,但是不好懂!
所以基本上,有時循環解決的問題號,又是則是遞歸,這就要看場合了。



下面舉一些例子來介紹遞歸,順帶引出上面提到的“場合”,進一步區分它們倆

eg1 :這裏引用大名鼎鼎的《C Primer Plus》書上的最初例子(稍微該簡短了些,詳細見第六版P221)

#include <stdio.h>
void up_and_down(int a){
   
   
	printf("Level %d\n",a);
	if(a < 4)
		up_and_down(a + 1);//遞歸
	printf("LEVEL %d\n",a);//大小寫利於區分
}
int main(void){
   
   
	up_and_down(1);//最初給n賦值1
	return 0;
}
	

最終結果是:
在這裏插入圖片描述
這裏用我自己的大白話+畫圖來解釋一下啦~
我們先來看看遞歸過程中的“去“
在這裏插入圖片描述



再來看看”回“

在這裏插入圖片描述

*這裏爲啥要故意每個箭頭拐一下呢?是因爲要先回到上一級調用結束,才能跳出花括號進入下一條語句~

這裏小白博主剛開始腦袋秀逗,以爲花括號外即是else,所以導致想了很久纔想明白。。。
這樣一畫圖一理解,相信應該很好理解————吧?

相同的,這樣利用遞歸思路的解題還有很多
譬如”利用遞歸來寫一個代碼——從鍵盤輸入一串字符,程序幫忙打印出來”

在這裏插入圖片描述
算法思路就是:利用遞歸和求餘,當a是一個兩位數字以上的數字時,讓它遞歸除以10,得到前兩位數字,不斷遞歸,直到最後一個數字,再求餘求回來。

結果如下:
在這裏插入圖片描述
接着舉一個很有名的例子——斐波那契數列

先介紹一下斐波那契額數列(即第三位數字永遠是前兩項的和)
:1 1 2 3 5 8 13 21 34 55…

思路:(數列數列,從小老師就教我們看到數列就去想通項公式嘛!)

在這裏插入圖片描述
所以我們就可以很好地想到遞歸思路,然後寫出以下代碼:
在這裏插入圖片描述
這樣看起來真的很簡單,但是當你將n賦值一個較大的數字時,比如40
程序就卡住了?!
別慌,這不是咱程序寫錯了,而是你得耐心,得給你寶貝電腦一些時間(doge 恐怕終於你等到了,算出來也是個越界的數字。。)
這就納悶了,爲啥呢?
學過數學的我們都知道,要想求第40個斐波那契數列,我們需要第39個和第38個,而第39個我們需要38和37,第38個我們需要37和36…
在這裏插入圖片描述
光是一個37,我們就重複計算了很多次。該函式使用了雙遞歸,即函數每一集遞歸都要都調用本身兩次
所以導致這些變量呈指數性增長,很快就消耗掉計算機內存導致棧溢出。









所以這裏就引出了文章剛開始提到的“場合”問題,這裏到底該用遞歸還是循環呢?

答案一定是循環,這也即是體現它們倆優缺點的明顯區別。
將程序改寫成用循環寫:
在這裏插入圖片描述
這樣同樣可以解決問題,但是效率是遞歸的數倍。
所以以後考慮用到循環的問題,可以想想遞歸思路,但是也要想想其複雜度問題~(本人還沒學過數據結構QAQ,所以我也不懂)



最後的最後,還有一個很著名的問題想和大家分享一下~~
——————漢諾塔問題(Hanio Tower)

漢諾塔問題:
首先要想解決它,你得先知道,啥是漢諾塔(說實話要不是C語言問題中有提到這一問題的話,我也不知道哈哈哈)
簡單概括一下就是說,有A,B,C三根柱子,其中剛開始A柱子上有N個圓盤,(從上往下)從小到大,最終目標是,通過B柱子的輔助,將A柱子上的圓盤移動到C柱子上去,過程中,要遵循從上往下,從小到大的規律!(也即大盤子不能放在小盤子上)。
問:要移動幾次?


在這裏插入圖片描述
其實看似有點難懂的問題裏,這其實就是一個遞歸問題。
但是本人認爲,如果你不將除了最下面那塊最大的以外,即(n-1)個圓盤看成整體的話,不太好想~

思路:始終秉着一個目的,將當前最大的那塊移到C盤上去。

最初版本(本人認爲比較垮。。)
在這裏插入圖片描述
修改後
在這裏插入圖片描述
兩個結果都一樣如下
在這裏插入圖片描述




總結
C語言中函數規定,可以自己調用自己。那麼既然如此就不能白白浪費這一特性,當然還是要看“場合”,因爲遞歸效率實在是太低了。。

QAQ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章