關於漢諾塔問題我思考了一段時間。最後總結原因之前想不明白還是對遞歸問題沒有深入理解。我的另一篇博文《遞歸詳解》已經很好的介紹了遞歸的原理。
分析漢諾塔問題:由以下三步組成
1 用C做過度,將A柱上的n-1個盤子直接移到C柱上
2 將A柱上的最後一個盤子移動到C柱上。
3 用A做過度,將B柱上的n-1個盤子直接移到C柱上
由此將移動n個盤子的漢諾塔問題歸結爲移動n-1個盤子的漢諾塔問題
然後我們要知道:其實遞歸和自己編寫遞歸函數的方法是相反的。當你要寫一個遞歸函數時你只需要做2步:
1. 在程序中不要把對n-1的調用看做一個一層層深入下去的調用,而只是把他看做一個可以立即完成n-1任務的指令。並使用這個指令解決事件n的問題。
2 將終止遞歸條件適當的放到程序中。(一般的放置位置都是如下放在if條件語句中)
現給出遞歸函數的模板如下:
Result M(Problem prob)
{
if (<problem can be solved easily>)
return <easy solution>;
// The problem cannot be solved easily.
Problem smaller1 = <reduce problem to smaller problem>
Result result1 = M(smaller1);
Problem smaller2 = <reduce problem to smaller problem>
Result result2 = M(smaller2);
...
Result finalResult = <combine all results of smaller problem to solve large problem>
return finalResult;
}
最終我們將漢諾塔的代碼實現如下:
#include <iostream>
using namespace std;
void Move(int n,char x,char y){
cout<<"把"<<n<<"號從"<<x<<"挪動到"<<y<<endl;
}
void Hannoi(int n,char a,char b,char c){
if(n==1)
Move(1,a,c);
else
{
Hannoi(n-1,a,c,b);
Move(n,a,c);
Hannoi(n-1,b,a,c);
}
}
int main()
{
cout<<"以下是7層漢諾塔的解法:"<<endl;
Hannoi(7,'A','B','C');
cout<<"輸出完畢!"<<endl;
system("pause");
}