最近呢也是有好久沒有更新博客了,主要是由於平時比較忙,畢竟等疫情完全解封qj我也要小升初考試了,因此打算趕在今天更新點乾貨。ios
在各大oi賽事上,遞歸和遞推算是個基礎而重要的算法,遞歸在熟練運用後能夠實現dfs,dfs是深度優先搜索,之後會講到關於dfs的;而遞推是一種用若干步可重複運算來描述複雜問題的方法,好比斐波那契數列,上樓梯等都是能夠經過遞推來進行實現的,而下一講即將會具體講述遞推,今天的主題是遞歸 c++
如今切入正題算法
一.遞歸框架
遞歸函數其實在比賽中特別常見,不少人在比賽的時候遇到不會的題就直接打暴力,可是若是你會遞歸的話,你能夠用一通pmn或者dfs直接爆搜(據有關人士稱,去年提升組若是pmn能夠的200+。。。)那到底什麼是遞歸呢?遞歸函數,便是本身調用本身,理解遞歸最好是經過一個例子來理解,好比,超經典的基礎題,1+2+3+4+...+n-2+n-1+n=?遇到這個題,通常作法是利用for循環一個一個的累加,提供一個c++代碼函數
#include<bits/stdc++.h>//萬能頭文件,建議比賽時使用 using namespace std; int s,i,n; int main() { S=0;
cin>>n; for(i=1;i<=n;i++) s=s+i; cout<<s; return 0; }
這是最簡單也最直觀的代碼,若是使用遞歸實現雖然會看起來麻煩一點,但對遞歸的理解有好處。算法的流程圖大概是是這樣的過程有點相似於倒着的for法,結合代碼咱們一塊兒看看,運行結果是同樣的網站
#include <iostream> using namespace std; int dg(int n) //遞歸函數,n定義的是局部變量不衝突 { if(n==1) return 1; return (dg(n-1)+n);//進行遞歸 } int main() { int n; cin>>n; cout<<dg(n); return 0; }
大概就是這樣子的,遞歸的一個基本的主體框架有兩個部分,一個是反覆遞歸的過程,還有就是停止條件,否則你的程序停不下來可很悲催的一件事,相信我,程序死活不輸出你也找不到問題所在,只能瀏覽程序了,到了後期,這些細節要愈加的注意,由於如今我寫代碼都動不動65+行,好比高精度就要佔你數十行;spa
#include <iostream> using namespace std; int dg(int n) //遞歸函數,n定義的是局部變量不衝突 { if(終止條件) return 停止的返回值; dg(n-1);//進行遞歸 (舉例) //遞歸的形式須要根據須要而調整,好比有時候你也許會是是dg(n+1)+n; } int main() { dg(n); //調用遞歸函數 return 0; }
遞歸的基本模板👆;code
重點是本身調用本身這一塊比較難理解,能夠本身試圖去嘗試寫一些遞歸程序blog
這裏再和你們分享一道經典的題:排序
設有n個數已經按從大到小的順序排列,如今輸入x,判斷它是否在這n個數中,若是存在則輸出yes,不然輸出 no;
拿到題目先分析(這裏節省點位置,流程圖留給大家本身去畫吧🙂),這是一道比較簡單的數據查找的問題,通常使用順序查找,使用for循環,這個for循環也能夠「遞歸化」;分別展現一下for作法和遞歸作法(其實還有一個作法會在將來講二分查找的時候講)
#include <bits/stdc++.h>//萬能頭能夠省好多事 using namespace std; int main(){ int a[10];//用於錄入10個數 int n; for(int i=0;i<10;i++) cin>>a[i]; sort(a,a+10); //快速排序函數庫,加了萬能頭就不用加它的頭文件了 cin>>n; for(int i;i<10;i++) { if(a[i]=n) { cout<<"yes"; return 0; } } cout<<"no"; return 0; }
#include <bits/stdc++.h>//萬能頭能夠省好多事 using namespace std; int a[10];//用於錄入10個數 bool b=false; void fun(int n,int k) { if(n==a[k]) { b=true; return; }//找到了,標記一下,直接跳出,不須要再找了 else if(k<0) return; //所有找完都沒找到,也不用找了 fun(n,k-1);//調用部分 } int main(){ int n; for(int i=0;i<10;i++) cin>>a[i]; sort(a,a+10); //快速排序函數庫,加了萬能頭就不用加它的頭文件了 cin>>n; int k=9;//下標從0開始 fun(n,k); if(b) cout<<"yes"; else cout<<"no"; return 0; }
註釋 上:for遍歷法 遞歸遍歷法 敬請期待二分查找(還不快關注。。。)
上面的作法都是可行的,運行結果一切正常。
博客留題!:
洛谷遞歸題單 https://www.luogu.com.cn/training/109#problems
酌量練習,把握分度,否則會沉迷於洛谷這個花花綠綠的遊戲網站 (劃去)
今天的內容就是這些了,下次會講遞推,還會分享一些資料,假如你有興趣,先點贊👍,關注➕走一波,關注後歡迎白嫖😀;