谈到递归,我们可以想到很多问题:羊下崽,青蛙跳台阶,以及最令人头疼的问题,也就是我们今天将要讲的:汉诺塔(hanoi)问题。
那么首先,我想给大家先讲汉诺塔的故事,让大家对其有一个基本了解:
汉诺塔问题源自印度一个古老的传说,印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱,其中的一根柱子上按照从小到大的顺序摞着 64 个黄金圆盘。梵天命令一个叫婆罗门的门徒将所有的圆盘移动到另一个柱子上,移动过程中必须遵守以下规则:
每次只能移动柱子最顶端的一个圆盘;
每个柱子上,小圆盘永远要位于大圆盘之上;
给大家一个图康康:
而最后我们需要达到这样的结果:
汉诺塔问题中,三个圆盘移动需要7次,我们可以推广到n个圆盘移动需要2n-1次
接下来我们就开始进行分析,逐个击破
首先我们假设一二三柱分别为:A,B,C,A为起始柱,B为辅助柱,C为目标柱
首先只有一个盘子的时候,很简单,直接A->C
而两个盘子的时候,A->B,A->C,B->C
三个盘子:A->C,A->B,C->B,A->C,B->A,B->C,A->C
其实我们可以发现,我们每次进行的,就是除了最大的盘子,将上面的n-1个盘子,先移到辅助柱上,然后将最大的盘子移到目标柱上,之后则是重复这一过程。
而代码如下,相信大家看完代码和注释后,对于其理解可以更加深刻
void move(char pos1, char pos2) {
printf("%c->%c ", pos1, pos2);
}
//n代表盘子的个数
//source代表起始位置
//auxiliary代表中转位置
//target代表目标位置
void hanoi(int n, char source, char auxiliary, char target) {
if (n == 1)
move(source, target);
else
{
hanoi(n - 1, source, target, auxiliary);//n-1个盘子,将source作为起始位置,将target作为中转位置,将auxiliary作为目标位置
move(source, target);//大盘子从source移动到target
hanoi(n - 1, auxiliary, source, target);//中间所在的柱子作为起始位置,source作为中转位置,而target为目标位置
}
}
int main()
{
hanoi(1, 'a', 'b', 'c');
printf("\n");
hanoi(2, 'a', 'b', 'c');
printf("\n");
hanoi(3, 'a', 'b', 'c');
return 0;
}
代码结果:
希望大家都能从这篇文章中学到东西!如果大家还有什么想法也可以来找我探讨!