一個例子,讓孩子理解遞歸函數,何爲遞歸,何爲遞,何爲歸(C++)

情景構建:

        將一個三位數倒序輸出。

一、解:

#include<bits/stdc++.h>
using namespace std;


void Dxs1(int n){
	cout<<n;
}

void Dxs2(int n){
	cout<<n%10;
	Dxs1(n/10);
}

void Dxs3(int n){
	cout<<n%10;
	Dxs2(n/10);
}

int main(){
	Dxs3(123);
	return 0;
}

二、合併:

#include<bits/stdc++.h>
using namespace std;


void Dxs(int n){
	if(n==1){
		cout<<n;
	}else{
		cout<<n%10;
		Dxs(n/10);
	}
}

int main(){
	Dxs(123);
	return 0;
}

疑惑:函數沒執行完,再次調用能行嗎?

解答:去啃函數調用過程,棧幀。

說人話:函數就像公式,參數就像數據。

做人事:腦子不夠紙條來湊。

三、優化:

#include<bits/stdc++.h>
using namespace std;


void Dxs(int n){
	cout<<n%10;
	if(n>10)Dxs(n/10);
}

int main(){
	Dxs(123);
	return 0;
}

思路:輸出個位,n降權。

“遞”:Dxs(n/10)——逐步去掉個位的過程。

四、更懵逼或者有通達:

#include<bits/stdc++.h>
using namespace std;


void Dxs(int n){
	if(n>10)Dxs(n/10);
	cout<<n%10;
}

int main(){
	Dxs(123);
	return 0;
}

問題:在“遞”之後輸出,輸出結果是什麼?

五、設計遞歸函數還得先按部就班,沒有正確代碼,你是想優化BUG嗎?

0、相同操作是什麼?會退化爲不用調用遞歸函數嗎?不滿足這兩者,就不要遞歸了,沒有相同操作還用調用自身嗎?沒有邊界你要遞到哪?無限循環了好不好。

1、形參是什麼,返回值要不要有?——做什麼——函數入口(也是整個遞歸的入口)

2、何時退出?——做到什麼程度——函數出口(也是整個遞歸的出口)

3、何時調用自身?——怎麼做——函數調用

六、閒聊

1、遞歸函數和非遞歸函數調用起來沒區別。也就是說,遞歸佔用棧空間,默認棧空間有1024*1024byte,太深的遞歸就崩了,而且進出棧也會消耗時間。

2、遞歸都可以轉化爲循環或用stack(棧)結構實現。但是,在解決複雜問題時,使用遞歸或棧可以更容易的把精力集中在子問題的求解上。例如可以很方便的使用增量式或表式記錄進行剪枝,即提高效率又避免崩掉。

3、遞歸、stack實現的都是深度優先遍歷。

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