前言
汉诺塔问题
汉诺塔(Tower of Hanoi)问题源于印度传说。话说大梵天创造世界时造了三根金钢石柱子(假设为A、B、C),其中一根柱子(假设为A)自底向上叠着64片大小不同的黄金圆盘。有一天,大梵天命令婆罗门把圆盘从A柱移动C柱上。并且规定,在柱子间移动圆盘时,每次只能移动一个圆盘,且任何时候大圆盘不能放在小圆盘上。
并给出算法代码,打印出来移动顺序。
一、算法分析
要把64个盘子从A座移动到C座,需要移动大约2的64次方盘子。一般人是不可能直接确定怎样移动盘子的每一个具体步骤。假如,有一个人想:如果有第二个人能有办法将上面63个盘子从A座移动到另外一座,第一个人再将最后一个盘子移动到C座,再命令第二个人将63个盘子从B座移动到C座,至此任务就完成了。
但是,有一个问题实际尚未解决,第二个人怎么样将63个盘子从A座移动到B座? 为了解决将63个盘子从A座移动到B座,第二个人又想,如果有人能够将62个盘子从一座移动到另外一座,就可以将63个盘子从A座移动到C座,他是这么做的:
(1)命令第三个人将62个盘子从A座移动到C座;
(2)自己将1个盘子从A座移动到B座;
(3)再命令第三人将62个盘子从C座移动到B座。
这样,还是有一问题还没有解决,怎样将62个盘子移动到C座?
这就需要运用递归思想:
递归(Recursion),指在函数的定义中使用函数自身的方法,即程序的自身调用,常用于描述以自相似方法重复事物的过程。但是,使用递归思想,必须有限制条件,在这个题中,递归结束的条件是 最后一个人只须移动一个盘子,否则递归还需要继续进行。
必须说明,只有当第64个人的任务完成后,第63个人的任务才能完成,所以,只有当2-64个人任务完成后,第一个人任务才能完成(每个人完成任务都必须完成一次递归)。因为第二步只需移动一个盘子,可以直接实现,但是第(1),(3)步并不是能够直接完成。
第(1)步又可用递归方法分解为:
1,将A座上1个盘子从A座移动到C座;
2,将A座上1个盘子从A座移动到B座;
3,将C座上一个盘子从C座移动到B座。
第(3)步也可用递归方法分解为:
1,将B座上1个盘子从B座移动到A座上;
2,将B座上1个盘子从B座移动到C座上;
3,再将A座上1个盘子从A座移动到C座上。
所以,可以直观的看出来,在一次递归调用中,又富含两个小递归,才能完成一次真正的递归。
如图所示:
将以上总和起来,可以得到移动3个盘子的步骤为:
A->C,A->B,C->B,A->C,B->A,B->C,A->C
以上盘子的移动顺序,为每一次递归,需完成的。
因此,由上面的分析可知:将n个盘子从A座移动到C座可以分解为三个步骤:
(1)将A座上n-1个盘子借助C座先移动到B座上;
(2)把A座上剩下的一个盘子移动到C座上;
(3)将n-1个盘子从B座上借助A座移动到C座上。
因此,可以把上面三个步骤分成两类操作:
(1)(n>1)时,将n-1个盘子移动到另外一个座上,这一步是最重要的一步,里面包含 3个步骤,方可完成,这是一个递归的过程,即将每个人的任务层层下方,知道第64个人为止。
(2)将1个盘子从一个座上移动到另一个座上。
二、
1.编写程序整体思想
用两类函数实现以上两类操作,用Father函数实现上面第一类操作用 Father(n,one,two,three)
表示将n个盘子从one 座移动到 three座的过程 需借助two座。
用 move函数(x,y)表示最终结果的输出,即将一个盘子从一个座上移动到另外一个座上。
可以分析出,最终将一个盘子移动,完成递归,只能从A座移动到C座上,这就为程序提供了很大的方便。
2.程序
#include<stdio.h>
void Father(int n,char one,char two,char three)
{
void move(char x,char y); //调用move函数
if(n==1)
move(one,three); //将n==1作为限制条件
else
{
Father(n-1,one,three,two);//当n>=2时,步骤1,先把最上面的一大堆n-1个小盘子从A移动到B
move(one,three);//此时A上就剩下第你n个大盘子,只需要从A移动到C
Father(n-1,two,one,three);//此时需要将B上的n-1个小盘子从B移动到C
}
}
void move(char x,char y) //定义move函数
{
printf("%c-->%c\n",x,y); //打印输出顺序
}
int main()
{
int m;
printf("请输入总共的盘子数");
scanf("%d",&m);
Father(m,'A','B','C');
return 0;
}
下面 我们输入 3,会出现以下结果:
总结
以上对递归函数作了比较详细的介绍,与应用,并根据汉诺塔问题,进行了分析,和编写相应程序,对递归的巧妙应用,简单化的解决了复杂问题。