0基礎演算法基礎學演算法 第六彈 遞迴

球君發表於2020-04-18

  最近呢也是有很久沒有更新部落格了,主要是因為平時比較忙,畢竟等疫情徹底解封qj我也要小升初考試了,所以打算趕在今天更新點乾貨。

  在各大oi賽事上,遞迴和遞推算是個基礎而重要的演算法,遞迴在熟練運用後可以實現dfs,dfs是深度優先搜尋,以後會講到關於dfs的;而遞推是一種用若干步可重複運算來描述複雜問題的方法,比如斐波那契數列,上樓梯等都是可以通過遞推來進行實現的,而下一講即將會具體講述遞推,今天的主題是遞迴 

現在切入正題

一.遞迴

  遞迴函式其實在比賽中特別常見,很多人在比賽的時候遇到不會的題就直接打暴力,但是如果你會遞迴的話,你可以用一通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+行,比如高精度就要佔你數十行;

#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;
}

遞迴的基本模板?;

重點是自己呼叫自己這一塊比較難理解,可以自己試圖去嘗試寫一些遞迴程式

這裡再和大家分享一道經典的題:

  設有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

  酌量練習,把握分度,不然會沉迷於洛谷這個花花綠綠的遊戲網站 (劃去)

  今天的內容就是這些了,下次會講遞推,還會分享一些資料,假如你有興趣,先點贊?,關注➕走一波,關注後歡迎白嫖?;

相關文章