前言
汉诺塔问题是一道经典是计算机中的递归算法题,如果理解了汉诺塔问题就能更容易地理解函数的递归。
函数递归
函数递归的意思是函数自己调用自己。
函数递归的主要思想
把一个大问题一层一层的拆分成一个个问题类似,但规模较小的小问题,直到问题小到不能被拆分,递归就结束了,所以递归的思考过程就是大事化小的过程。
函数递归的递是递推的意思,归是回归的意思
函数递归有两个必要条件
1.递归要有结束条件,当该条件成立时,函数递归就不在进行。
2.函数每次递归都要越来越接近这个结束条件。
汉诺塔
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
下图是汉诺塔的简易动图
题目
用C语言实现以下功能:输入在A柱的盘子数,输出所有盘子从A柱移动到C柱的过程
题目思路
输入A柱有n个盘子,将n-1个盘子从A柱借助C柱移动到B柱,在将第n个盘子从A柱移动到C柱
步骤1:将n-1个盘子从A柱借助C柱移动到B柱
步骤2:将第n个盘子从A柱移动到C柱
步骤3:将n-1个盘子从B柱借助A柱移动到C柱
那如何移动n-1个盘子呢
以步骤3为例:把前n-1个盘子这个整体从B柱移到C柱的过程中,这个整体又可以划分为前n-2个盘子为一个整体和第n-1个盘子
重复步骤一,但是是从B柱借助C柱移动到A柱
重复步骤二,但是是从B柱移动到C柱
发现了吗,我们已经将这个问题拆分一次
把n-1个盘子从B柱移动到A柱,把n-1个盘子从B柱移动到C柱这些。当然,在移动n-2个盘子的过程我们还会极进行拆分,拆分成无数的小问题。这些无数的小问题们直到遇见步骤2的时候,也就是只有一个盘子的时候,才不会再进行拆分,直接移动这1个盘子即可。
该递归问题的结束条件是什么呢
就是当盘子只剩一个时,即n==1时
函数实现
以此类推,当汉诺塔上的圆盘数为n个时该如何移动,只需要按照上面的步骤一步步递归下去,最终是可以达到目的的。程序如下:
int count = 0;
void move(int n, char x, char y)
{
printf("第%d个盘子从 %c 柱移动到 %c 柱\n", n, x, y);
count++;
}
// 盘子数量 起始柱 功能柱 目标柱
void hannuo(int n, char A, char B, char C)
{
if (n == 1)//递归函数的结束条件
{
move(n, A, C);
}
else
{
//第一步,将A柱的n-1个盘子移动到B柱,
//此时,A柱为起始柱,C为功能柱,B柱为目标柱
hannuo(n - 1, A, C, B);
//第二步,将最大的盘子移动到C柱
//此时,A柱为起始柱,C柱为目标柱
move(n, A, C);
//第三步,将n-1个盘子移动到C柱
//此时,B柱为起始柱,A柱为功能柱,C柱为目标柱
hannuo(n - 1, B, A, C);
}
}
int main()
{
int n = 0;
char A = '0';
char B = '0';
char C = '0';//设置柱子
printf("请输入要移动盘子的数量");
scanf("%d", &n);//设置要移动盘子的数量
hannuo(n, 'A', 'B', 'C');
printf("一共移动了%d次盘子", count);
return 0;
}
运行结果
结语
感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!