C語言中的遞歸算法

目錄

 

一.什麼是遞歸?

二.例題


一.什麼是遞歸?

程序調用自身的編程技巧成爲遞歸(recursion)。

遞歸作爲一種算法在程序設計語言中廣泛應用。一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它通常把一個大型複雜的問題層層轉化爲一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重複計算,大大地減少了程序的代碼量。

遞歸的主要思考方式在於:把大事化小。

遞歸的兩個必要條件:

  • 存在限制條件,當滿足這個限制條件的時候,遞歸便不再繼續。
  • 每次遞歸調用之後越來越接近這個限制條件。

二.例題

1.接受一個整型值(無符號),按照順序打印他的每一位。

例如:

輸入:1234,輸出:1 2 3 4.

#include<stdio.h>
#include<stdlib.h>

//打印這個數字的每一位
//x=>1234
void PrintNum(int x){
    if(x>9){
        //x多於一位
       PrintNum(x/10); 
    }
        //x就是1位數
        printf("%d",x%10);
}
int main(){
    PrintNum(1234);
    system("pause");
    return 0;
}

2.編寫函數不允許創建臨時變量,求字符串的長度。

(1)遞歸算法。

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
int Strlen(char* str){
    if(*str=='\0'){
        //str指向的是一個空字符串
        return 0;
    }
    //str指向的不是一個空字符串,當前字符是字符串中的一個元素
    //hello ,str=>h 整個字符串的長度就爲
    //1+"ello"字符串的長度
    return 1+Strlen(str+1);
}

int main(){
    printf("%d\n",strlen("hello"));
    system("pause");
    return 0;
}

(2)非遞歸算法。

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
//實現求一個字符串的長度
//C語言中的字符串是通過字符數組的形式來模擬的
//字符數組本質上就是一個普通的數組,只不過每個元素的類型是char
//C風格字符串,會在數組的最後一個元素中填充成 、0 作爲字符串的結束標誌
//雖然C語言的字符串是字符數組,但是很多情況下也可以使用一個
//char* 指向字符數組的第一個元素,然後用這個指針來表示字符串
int Strlen(char* str){
         int count=0;
         //解引用
         while(*str!='\0'){
             ++count;
             ++str;
         }
        return count;
}

int main(){
    // "hello"字符串,佔用6個字節的空間
    //但是字符串長度爲5(沒算\0)
    printf("%d\n",Strlen("hello"));
    system("pause");
    return 0;
}

3.求n的階乘。(不考慮溢出)

(1)遞歸算法。

#include<stdio.h>
#include<stdlib.h>
 //1.先看 n 是不是1,如果是1直接返回1
 //2.如果n不是1,計算n*Factor(n-1)
int Factor(int n){
  if(n==1){
      return 1;
  }
  return n*Factor(n-1);
}
int main(){
    //珠腦速算
    //1*2*#*4*5 =>120
    printf("%d\n",Factor(5));
    system("pause");
    return 0;
}

(2)非遞歸算法。

#include<stdio.h>
#include<stdlib.h>
int Factor(int n){
    int result=1;
    for(int i=1;i<=n;++i){
        result *= 1;
    }
    return result;
}
int main(){
    //珠腦速算
    //1*2*#*4*5 =>120
    printf("%d\n",Factor(5));
    system("pause");
    return 0;
}

4.求第n項斐波那契數(不考慮溢出)。

斐波那契數列是指這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波那契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)。

(1)遞歸算法。

#include<stdio.h>
#include<stdlib.h>
//求第n項斐波那契數列
int Fib(int n){
    if(n==1||n==2){
        return 1;
    }
    return Fib(n-1)+Fib(n-2);
}
int main(){
    printf("%d\n",Fib(6));
    system("pause");
    return 0;
}

(2)非遞歸算法。

#include<stdio.h>
#include<stdlib.h>
int g_count=0;
//求第n項斐波那契數列
//s
//ms    1s=>1000ms
//us    1ms=>1000us
//ns    1us=>1000ns
int Fib(int n){
    if(n==1||n==2){
        return 1;
    }
    //表示i-2項和i-1項的內容
    int num1=1;
    int num2=1;
    int result=0;  //最終的 第n項 的結果
    for(int i=3;i<n;++i){
        result=num1+num2;
        num1=num2;
        num2=result;
    }
    return result;
}

//解決一個問題,往往既可以使用遞歸的方式,也可以使用非遞歸(循環)的方式
//遞歸的方式代碼通常更直觀更簡單,但是運行效率可能會較低
//非遞歸方式代碼通常更繁瑣,但是運行效率可能會較高
int main(){
    printf("%d\n",Fib(40));
    printf("%d\n",g_count);
    system("pause");
    return 0;
}

       上述兩種代碼,一種是遞歸另外一種是非遞歸,相較於非遞歸而言,遞歸算法更簡潔,但是其運行效率也可能相對較低,而非遞歸算法雖然寫起來複雜,但是運行效率卻相對來說要更好些。

 

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