汉诺塔问题
在复习栈之前,先复习一下递归,当时学递归的时候百思不得其解,甚至还自己去模拟了递归的每一步操作,后来发现这个工作量实在太大,今天还是以经典的汉诺塔问题来复习一下递归
什么是递归
递归,简单来说就是自己调用自己,看过《武林外传》的小伙伴应该都记得姬无命那句话“我杀了我”,没错,递归就是这样的一个东西。
在数据结构教材上,对递归的定义很复杂,看了半天也不知道在讲什么。
如图,是教材上的解释
看起来很复杂对不对,反正也看不懂,那就不看了,只需要记住划出来的那句话,退出第i层递归应返回上一层。基于这个理解,我们来看看汉诺塔问题。
汉诺塔问题
汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
我们把汉诺塔问题简化成XYZ三根柱子,在A柱子上有n个圆盘,从上到下圆盘依次增大,编号是1-n,每次移动一个圆盘,要将柱子X上面的圆盘全部移动到Z上,并且顺序不变,中间任何时刻也不能出现大圆盘在小圆盘上面的情况。
1.先来看第一种情况,如果只有一个圆盘,这个就直接移动。
2.第二种情况,如果有两个圆盘,我们这样移动:把1从X移动到Y,把2从X移动到Z,最后把1从Y移动到Z
3.如果三个圆盘呢?1从X移动到Z,2从X移动到Y,1从Z移动到Y,3从X移动到Z,1从Y移动到X,2从Y移动到Z,最后再把1从X移动到Z
将前面3个步看成整体,后面三步看成整体,最后就成了三步
首先将n-1个在X上的圆盘借助Z移动到Y,再将A上的编号为n的圆盘移动到Z,最后将n-1个在Y上的圆盘借助X移动到Z。有了这个思路,接下来就可以实现了
代码
#include<iostream>
using namespace std;
void move(int id,char from,char to)
{
cout << "把" << id << "从" << from << "移动到" << to << endl;
}
void hanoi(int n, char x, char y, char z)
{
if (n == 0) {
return;
}
else
{
hanoi(n - 1, x, z, y);//第一步
move(n, x, z);//第二步
hanoi(n - 1, y, x, z);//第三步
}
}
int main()
{
int n;
cout << "请输入个数n" << endl;
cin >> n;
hanoi(n, 'A', 'B', 'C');
system("pause");
return 0;
}