汉诺塔:简单来说,就是一个大盘子
和一堆小盘子
的移动游戏。
先把小盘子们
移到中间,再把大盘子
移到最后,最后把小盘子们
摞到大盘子
上面。
如果是两个盘子
,小盘子移到中间,大盘子移到最后,小盘子再放到大盘子上面来,很符合这个流程。
如果是三个盘子呢,此时我们应该分开来看。
先不看大盘子
,对小盘子们
来说,它们的目标是全部放到中间
。这么来看,两个小盘子
又是一个汉诺塔问题,只不过我们最开始说的“中间”对新的汉诺塔问题而言,变成了“最后”。
好像有些抽象,我们编号看看。
我们标记整个问题:A为起始,B为中间,C为目标。
对于两个小盘子来说:A为起始,B为目标,C为中间。
我们先忽略大盘子
,当它不存在,处理小盘子
。移动两个汉诺塔,还是很简单的。
进行汉诺塔排序:A——>C,A——>B,C——>B。完成了整个过程。两个盘子的游戏结束。
再让大盘子
回来,并且执行A——>C。
此时两个小盘子
又是一个经典的汉诺塔问题,而且B成了起始柱,A成了中间柱,C成了目标柱。
再进行一次汉诺塔排序:B——>A,B——>C,A——>C。
汉诺塔排列完成。
那么根据这个过程,我们来写代码:
void hanoi(int n, char A, char B, char C) //三个柱子,总问题,A为起始,B为中间,C为目标。
{
if (n==1) //一个盘子的情况,起始——>目标
{
printf("%c——>%c\n", A, C);
}
else //两个盘子的情况,A为起始,B为目标,C为中间。
{
hanoi(n - 1, A, C, B); //起始——>目标,因为2-1=1,所以直接排
printf("%c——>%c\n", A, C); //大盘子A——>C
hanoi(n - 1, B, A, C); //小盘子从B目标转到C目标,因为2-1=1,所以直接排
}
}
所有的大于两个盘子的情况,都会落实到一次次的递归当中。我们关心的是一个盘子、两个盘子怎么移动,最多关心三个盘子怎么移动。每一次递归,柱子的定位都会发生改变,而盘子的变化是有限的。我们的思维认为,固定的柱子不变,活动的盘子移动,但在递归的过程中,柱子是在变化的。
#include <stdio.h>
void hanoi(int n, char A, char B, char C)
{
if (n==1)
{
printf("%c——>%c\n", A, C);
}
else
{
hanoi(n - 1, A, C, B);
printf("%c——>%c\n", A, C);
hanoi(n - 1, B, A, C);
}
}
int main()
{
hanoi(3, 'A', 'B', 'C');
return 0;
}