转载请注明出处,珍惜下劳动成果~~~
背景说明:
河内之塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学卷Edouard Lucas曾提及这个故事.据说创世纪时Benares有一座波罗教塔,是由三支钻石棒所支撑,开始时神在第一根棒上放置64个由上至下依由小至大一次排列的金盘,并命令僧侣将所有的金盘从第一根石棒移至第三根石棒,且搬运过程中遵守大盘子在小盘子之下的原则,若每日仅搬一个盘子,则当盘子全数搬运完毕时,此塔将毁损,而也就是世界末日来临之时.
----译自 世界经典算法
大天朝白话文:
就是说这有三根棒子,第一个棒子上有几个盘子(数量未定),盘子是大的在下边,小的在上边,依次排列,而规则就是你要将所有的盘子按同样的顺序移到第三根上,过程中,不管在哪个棒子上,都要遵守大盘子在下边,小盘子在上边的规则.
这个我在自学数据结构的时候(不要问我为什么C还不会就学数据结构,大学的C课程,你脑补一下原因,我当时以为我学会C了.),在递归里是很经典的例子.还依稀记得那一小节的名字是分治法思想.其实说白了就是递归的实现.
首先自己动手实现一下,我们要找规律.
当有一个盘子时,移动的次序的A->C.
当有两个盘子时,A->B,A->C,B->C.
当有三个盘子时,A->C,A->B,C->B,A->C,B->A,B->C.A->C.
当有四个盘子时,A->B,A->C,B->C,A->B,C->A,C->B,A->B,A->C,B->C,B->A,C->A,B->C,A->B,A->C,B->C.
以此类推.
首先根据数学的归纳总结思想,你会发现一个有趣的现象,1的时候A->C,2的时候A->B,3的时候A->C,4的时候A->B...........奇数A->C,偶数A->B.好,先记下.(笔算加脑补运行了很多个盘子,发现确实这样.)
然后截取一下过程,3个的时候,A->C,A->B,C->B,4个的时候,A->B,A->C,B->C,A->B,C->A,C->B,A->B.截取的过程发现,都是先把除最后一个盘子之外的所有盘子按序放到了第二个棒子上,然后将最大的盘子放到第三个棒子上,之后,就相当于第三个棒子还是没有东西,因为它上面放的是最大的盘子,任何盘子都能放到它的上面,这样问题就变成了,有三个棒子,第二个棒子上有按序放置的一叠盘子,要把它们全部移动到第三个棒子上,相当于1,2棒子互换了下位置.问题不变而已.典型的递归操作!
然后想想递归的思想,把大量的数据处理简化成小量的数据处理,即把大规模的处理分成多个小规模的处理(我比较讨厌记条条框框,所以理解意思就好,我不知道是不是对的上教条).根据这个,我们尝试写代码.首先写一个盘子的时候:
void hanoi(int n,char A,char B,char C) { if (n == 1) { printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); } }一个盘子的时候很简单,就是移动到第三根棒子上就可以,然后我们尝试写2个盘子的时候:
void hanoi(int n,char A,char B,char C) { if (n == 1) { printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); }else if (n == 2) { printf("将盘子 %d 从 %c 移到 %c \n", (n-1) , A ,B); printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); printf("将盘子 %d 从 %c 移到 %c \n",n-1 , B ,C); } }
void hanoi(int n,char A,char B,char C) { if (n == 1) { printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); }else if (n == 2) { hanoi(n-1,A,C,B); printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); hanoi(n-1,B,A,C); } }
void hanoi(int n,char A,char B,char C) { if (n == 1) { printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); }else { hanoi(n-1,A,C,B); printf("将盘子 %d 从 %c 移到 %c \n",n , A ,C); hanoi(n-1,B,A,C); } }
#include <stdio.h> #include <stdlib.h> void hanoi(int ,char ,char ,char); int main() { int n ; printf("请输入盘子数量 : n>0"); scanf("%d",&n);//这里scanf函数要传入个地址 hanoi(n,'A','B','C'); system("pause"); return 0; }
请输入盘子数量 : n>05
将盘子 1 从 A 移到 C
将盘子 2 从 A 移到 B
将盘子 1 从 C 移到 B
将盘子 3 从 A 移到 C
将盘子 1 从 B 移到 A
将盘子 2 从 B 移到 C
将盘子 1 从 A 移到 C
将盘子 4 从 A 移到 B
将盘子 1 从 C 移到 B
将盘子 2 从 C 移到 A
将盘子 1 从 B 移到 A
将盘子 3 从 C 移到 B
将盘子 1 从 A 移到 C
将盘子 2 从 A 移到 B
将盘子 1 从 C 移到 B
将盘子 5 从 A 移到 C
将盘子 1 从 B 移到 A
将盘子 2 从 B 移到 C
将盘子 1 从 A 移到 C
将盘子 3 从 B 移到 A
将盘子 1 从 C 移到 B
将盘子 2 从 C 移到 A
将盘子 1 从 B 移到 A
将盘子 4 从 B 移到 C
将盘子 1 从 A 移到 C
将盘子 2 从 A 移到 B
将盘子 1 从 C 移到 B
将盘子 3 从 A 移到 C
将盘子 1 从 B 移到 A
将盘子 2 从 B 移到 C
将盘子 1 从 A 移到 C
请按任意键继续. . .
完美执行!