汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
先假设除最下面的盘子之外,我们已经成功地将上面的63个盘子移到了b柱,此时只要将最下面的盘子由a移动到c即可。如图:
当最大的盘子由a移到c后,b上是余下的63个盘子,a为空。因此现在的目标就变成了将这63个盘子由b移到c。这个问题和原来的问题完全一样,只是由a柱换为了b柱,规模由64变为了63。因此可以采用相同的方法,先将上面的62个盘子由b移到a,再将最下面的盘子移到c……对照下面的过程,试着是否能找到规律:
- 将b柱子作为辅助,把a上的63个圆盘移动到b上
- 将a上最后一个圆盘移动到c
- 将a作为辅助,把b上的62个圆盘移动到a上
- 将b上的最后一个圆盘移动到c
- ......
也许你已经发现规律了,即每次都是先将其他圆盘移动到辅助柱子上,并将最底下的圆盘移到c柱子上,然后再把原先的柱子作为辅助柱子,并重复此过程。
下面列出C++代码:
#include <iostream>
#include <stack>
using namespace std;
stack<int> hanoitower_buid(int num)
{
stack<int> hanoitower;
for (int i = num; i > 0; i--) {
hanoitower.push(i);
}
return hanoitower;
}
void hanoitower_show(stack<int> sta)
{
stack<int> sta_temp;
while (!sta.empty()) {
int temp = sta.top();
sta.pop();
sta_temp.push(temp);
}
while (!sta_temp.empty()) {
int temp1 = sta_temp.top();
cout << " " <<temp1 << ends;
sta_temp.pop();
}
}
void hanoitower_move(int n, stack<int>& x, stack<int>& y, stack<int>& z)
{
if (n > 0) {
hanoitower_move(n - 1, x, z, y);
int temp = x.top();
x.pop();
y.push(temp);
hanoitower_show(x);
cout << endl;
hanoitower_show(y);
cout << endl;
hanoitower_show(z);
cout << endl;
cout << "-----------------------"<<endl;
hanoitower_move(n - 1, z, y, x);
}
}
int main()
{
stack<int> x, y, z;
x = hanoitower_buid(3);
hanoitower_move(3, x, y, z);
}
接下来放上(3)时的输出结果。
堆栈迭代无比强大!