情景構建:
將一個三位數倒序輸出。
一、解:
#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實現的都是深度優先遍歷。