1. 程式人生 > >C++遞迴演算法經典例項詳解

C++遞迴演算法經典例項詳解

/*--------------------------- 該段為引用----------- 遞迴演算法解決問題的特點: (1) 遞迴就是在過程或函式裡呼叫自身。 (2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。 (3) 遞迴演算法解題通常顯得很簡潔,但遞迴演算法解題的執行效率較低。所以一般不提倡用遞迴演算法設計程式。 (4) 在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存。遞迴次數過多容易造成棧溢位等。所以一般不提倡用遞迴演算法設計程式。

 ------------------------------------------------- */

說一下我對遞迴演算法的理解。

遞迴演算法的程式碼,可以分成兩個部分:遞迴出口(滿足輸出條件之類的)和遞迴部分(遞迴程式碼的主體)。

遞迴演算法特點之一就是把整體換成部分。比如階乘和全排列問題,都是把問題“降階”(待會看程式碼就知道什麼意思了。)

還有一個最重要的特點————————效率低,但是遞迴演算法作為入門級演算法還是很值得我這樣的小白研究的。

來看看幾個經典的問題。1.全排列 ,2.漢諾塔,3.階乘

1.全排列:給你一個數組,你把這個數組裡的數的所有排列方式寫列出來。

input {1,2,3}

output{1,2,3},{1,3,2},{2,3,1}......(懶得敲了)

程式碼:

#include <iostream>   
using namespace std;  
int n = 0;  
  
void swap(char *q ,char *p)  
{   //交換函式 
    int temp;  
    temp= *q;  
    *q = *p;  
    *p = temp;  
}   
   
void perm(char arr[],int k, int m )  
{  
    int i;  
    if(k >m)  
    {  
        for(i = 0 ; i <= m ; i++)  
        {  //遞迴結束出口,當數列只剩下一個數的時候輸出 
            cout<<arr[i]<<" ";  
               
        }  
        cout<<endl;   
    }  
    else  
    {  
        for(i = k ; i <=m;i++)  
        {  //遞迴部分 
            swap(arr[k],arr[i]);  
            perm(arr,k+1,m);  
            /*把陣列看成1{234}+2{134}+3{124}+4{123}
			再把{234}看成2{34}+3{24}+4{23}
			一直把整體化為部分,一直把大問題分解成小問題。*/ 
            swap(arr[k],arr[i]);  
        }  
    }  
}  
  
int main()  
{  
    char arr[] ="1234";  
    perm(arr,0,3);     
    return 0;  
}

2.漢諾塔問題

就是移環子的遊戲

這個也可以用遞迴演算法實現。

ABC分別是123柱子,程式碼思路大概是這樣的

把N-1層的環子先通過C移到B,最後再把第N層的最大的環子移到C,這個時候就剩下一個N-1層的新“塔”,那麼我們把他看成一個新的“塔”把B柱看成之前的A柱,通過C柱把(N-1)-1層移到A柱,再把第N-1層的最大(原本第二大)的環子放到C,如此迴圈最後N=1 就瞭解了。

#include<iostream>
using namespace std;
void hanoi(int n,char a,char b,char c)
{
if(n==1)
cout<<n<<" "<<a<<" "<<c<<endl;
else
{
hanoi(n-1,a,c,b);
cout<<n<<" "<<a<<" "<<c<<endl;
hanoi(n-1,b,a,c);
}
}
int main()
{
int n;
cout<<"輸入正整數:"<<endl;
cin>>n;
cout<<"結果為"<<endl;
hanoi(n,'A','B','C');
/*
假設有4層,跟全排列差不多的想法,先把他看成3層,再看成2層,而且移動的方法是相同的。*/ 
return 0;
} 
3.階乘……不講了。。