递归算法的出发点不是由初始条件出发,而是把出发点放在求解的目标上,从所求的未知项出发逐次调用本身的求解过程,直到递归的边界(即初始条件)。
汉诺塔问题的重点是分析移动的规则,找到规律和边界条件。
若需要将n个盘子从A移动到C就需要(1)将n-1个盘子从A移动到B;(2)将你第n个从A移动到C;(3)将n-1个盘子再从B移动到C,这样就可以完成了。如果n!=1,则需要递归调用函数,将A上的其他盘子按照以上的三步继续移动,直到达到边界条件n=1为止。
思路清楚了,程序就好理解了。程序中的关键是分析好每次调用移动函数时具体的参数和对应的A、B、C塔的对应的关系。下面来以实际的例子对照程序进行说明。
①move(int n,int x,int y,int z)
②{
③ if (n==1)
④ printf("%c-->%c\n",x,z);
⑤ else
⑥ {
⑦ move(n-1,x,z,y);
⑧ printf("%c-->%c\n",x,z);
⑨ {getchar();}//此句有必要用吗?感觉可以去掉的吧
⑩ move(n-1,y,x,z);
}
}
比如有4个盘子,现在全部放在A塔上。盘子根据编号为1、2、3、4依次半径曾大。现在要将4个盘子移动到C上,并且是按原顺序罗列。首先我们考虑如何才可以将4号移动到C呢?就要以B为中介,首先将上面的三个移动到B。此步的操作也就是程序中的①开始调入move函数(首次调用记为一),当然现在的n=4,然后判断即③n!=1所以不执行④而是到⑤再次调用move函数(记为二)考虑如何将3个盘移动到B的方法。此处是递归的调用所以又一次回到①开始调入move函数,不过对应的参数发生了变化,因为这次要考虑的不是从A移动4个盘到C,而是要考虑从A如何移动移动3个盘到B。因为n=3,故不可以直接移动要借助C做中介,先考虑将两个移动到C的方法,故再一次到⑤再一次递归调用move函数(记为三)。同理两个盘还是不可以直接从A移动到C所以要以B为中介考虑将1个移动到B的过程。这次是以B为中介,移动到C为目的的。接下来再一次递归调用move函数(记为四),就是移动到B一个,可以直接进行。程序执行③ ④句,程序跳出最内一次的调用(即跳出第四次的调用)返回上一次(第三次),并且从第三次的调用move函数处继续向下进行即⑧,即将2号移动到了C,然后继续向下进行到
⑩,再将已经移到B上的哪一个移回C,这样返回第二次递归(以C为中介将3个盘移动到B的那次)。执行⑧,将第三个盘从A移动到B,然后进入⑩,这次的调用时因为是将C上的两个盘移到B以A为中介,所以还要再一次的递归调用,对应的参数传递要分析清楚,谁是原塔谁是目标塔,谁是中介塔。过程类似于上面的分析,这里不再重复论述了。
不知道讲解清楚了没有,自己看书时感觉关键的地方在于函数参数的传递,参数和变量的对应关系对应清楚以后就可以了。
希望对你有所帮助,同时也祝你的问题早日得到解决,呵呵!
用断点看程序运行情况应该是最好的选择
在每一行都设一个断点,按F9
然后按F5运行
每运行一步都注意左下角当前变量的值的变化
从而一步步了解程序的运行情况
//代码如下:
//说明:A,B,C为三个载体,起始,中间,目的载体为相对的,
//1.将n-1个盘子从起始载体通过目的载体,移动到中间载体
//2.只有最后一个盘子了.你需要将最后一个盘子从起始载体移到目的载体即可
//3.再将n-1个盘子从刚才的中间载体通过起始载体移动到目的载体.完成
//4.在递归时遇到只有1个盘子那直接从起始介质移到目的介质就OK了.
//自己用纸画画吧,不太好理解.明白了就不难了.
#include
#define DISKA "A"
#define DISKB "B"
#define DISKC "C"
void move(int num,char *fromp,char *mediump,char *top);
void mv(char *fp,char *tp);
int main()
{
printf("please input the num of disk:");
int num;
scanf("%d",&num);
move(num,DISKA,DISKB,DISKC);
return 0;
}
void move(int num,char *fromp,char *mediump,char *top)
{
if(num == 1) {
mv(fromp,top);//4
} else {
move(num-1, fromp, top, mediump);//1
mv(fromp,top);//2
move(num-1, mediump, fromp, top);//3
}
}
void mv(char *fp,char *tp)
{
printf("%s--->%s\n",fp,tp);
}
这个,你最好找一张很大的纸,自己去画一下。数要小一些,不然会很发杂。具体过程不过是函数调用自身的过程。