C++遞迴演算法經典例項詳解
阿新 • • 發佈:2019-01-25
/*--------------------------- 該段為引用-----------
遞迴演算法解決問題的特點:
(1) 遞迴就是在過程或函式裡呼叫自身。
(2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。
(3) 遞迴演算法解題通常顯得很簡潔,但遞迴演算法解題的執行效率較低。所以一般不提倡用遞迴演算法設計程式。
(4) 在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存。遞迴次數過多容易造成棧溢位等。所以一般不提倡用遞迴演算法設計程式。
2.漢諾塔問題
------------------------------------------------- */
說一下我對遞迴演算法的理解。
遞迴演算法的程式碼,可以分成兩個部分:遞迴出口(滿足輸出條件之類的)和遞迴部分(遞迴程式碼的主體)。
遞迴演算法特點之一就是把整體換成部分。比如階乘和全排列問題,都是把問題“降階”(待會看程式碼就知道什麼意思了。)
還有一個最重要的特點————————效率低,但是遞迴演算法作為入門級演算法還是很值得我這樣的小白研究的。
來看看幾個經典的問題。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 就瞭解了。
3.階乘……不講了。。#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; }