从汉诺塔看递归

很开心今天搞明白了汉诺塔的方法递归。走了很多的弯路,今天分享自己的一些思考的过程以及结果。希望对有需要的同学们有所帮助。
题目:汉诺塔由三根柱子(分别用X、Y、Z表示)和n个大小互不相同的空心盘子组成。一开始n个盘子都摞在柱子X上,大的在下面,小的在上面,形成了一个塔状的锥形体。 对汉诺塔的一次合法的操作是指:从一根柱子的最上层拿一个盘子放到另一根柱子的最上层,同时要保证被移动的盘子一定放在比它更大的盘子上面(如果移动到空柱子上就不需要满足这个要求)。现在想要将盘子通过合法的操作从X移到Z。要求能显示盘片在移动中的每一搬动的走向。–题目出处来自由武汉大学出版社出版的**《C语言程序设计》**–主编 高建华 等教授们。

#include<stdio.h>
#include<conio.h> 
void move(int n,char s,char d);
void hanoi(int n,char x,char y,char z);
int main(void)
{
	int n;
	printf("输入汉诺塔问题的圆盘数量:");
	scanf("%d",&n);
	hanoi(n,'X','Y','Z');
	printf("请按任意键继续...");
	getch();
	return 0;
}
void hanoi(int n,char x,char y,char z)
{
	if(n==1)
	  move(n,x,z);
	else
	{
	  hanoi(n-1,x,z,y);
	  move(n,x,z);
	  hanoi(n-1,y,x,z);	
	}
}
void move(int n,char s, char d)
{
	printf("%d\t%c-->%c\n",n,s,d);
 } 

#include<stdio.h>
#include<conio.h>
//C语言的一个头文件,conio是ConsoleInput/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如getch()函数等等。具体涉及哪些函数我会在下面进行简单的补充,因为我对这方面也不是太明白,大家有需要的可以在csdn上看其他人的文章。//
void move(int n,char s,char d);
void hanoi(int n,char x,char y,char z);
//函数的使用前先声明,如果函数定义在主函数之前就不要再申明了(变相的声明),记住一定要在前面定义和申明必须有一个(当然也有在主函数里声明,但也是在主函数开头)//
int main(void)
{
int n;
printf(“输入汉诺塔问题的圆盘数量:”);
scanf("%d",&n);
hanoi(n,‘X’,‘Y’,‘Z’);
printf(“请按任意键继续…”);
getch();
//用任意键来结束程序,对于这种两端说明,好像系统自带,所以其实可以删printf(“请按任意键继续…”);getch();,所以上面的那个头文件也可以去掉了。//
return 0;
}
void hanoi(int n,char x,char y,char z)
{
if(n==1)
move(n,x,z);
else
{
hanoi(n-1,x,z,y);
move(n,x,z);
hanoi(n-1,y,x,z);
}
}
void move(int n,char s, char d)
{
printf("%d\t%c–>%c\n",n,s,d);//通过输出来表示盘子被移动//
}
//对于这段代码我之所以会困扰一段时间,是因为误入了一个误区,就是我试图和计算机一样一步一步的去执行去推导结果,往往因为数据太大而不了了之。而后我又尝试自己画了画试图直接将n推到1,结果也是因为,操作不易而放弃。归根结底我之所以,会犯错,就是因为没有真正理解递归的本质。//
//递归不就是n到n-1嘛,对只是没错的,而且是本质,但是很容易在写代码中忘却这一本质,拿我来说,试图从n来直接推。hanoi( n, x, y,z)写出来的就是将n个盘子从x移到z,你先别管函数里到底是啥步骤,就是一个黑盒子,里面就像是有魔法,一下子就实现了。 所以hanoi(n-1,x,z,y);这个就是将上面的n-1块盘子通过魔法的力量直接转移到Y这个柱子上,那么X上不就剩一块了么,于是就直接搬到Z就是了。再 hanoi(n-1,y,x,z);将之前的n-1块搬到Z上就行了。那可能会有同学问了,hanoi(n-1,x,z,y)这个又是咋将n-1块搬走的呢?回答因为有魔法,嘿嘿(自动狗头保命)。其实这里的魔法就是递归的作用,你不要纠结他到底咋递归的,你只要明白用了这个函数就可以实现,至于咋实现的。不要管他。那总不能啥都不管吧。管还是要管的,管的是啥,管的是起始项。
那啥是起始项。就是下面的n=2时。即X上只有2块盘子,将这两块盘子从X移到Z,借用Y来实现,这个就比较简单了。画图就OK了。自己动动手。
hanoi(1,x,z,y);
move(2,x,z);
hanoi(1,y,x,z); //
总而言之,递归就是在该函数定义时,调用该函数,但往往伴随n这种变量的变化。递归就像是第一数学归纳法一样,只要你将原有的基石打好就行了。只不过递归往往是从n推到1,而第一数学归纳法就k推到k+1;记住不要纠结中间到底有啥步骤,就当成黑盒子,变量一走就达到我们理想的结果。好了,今天就递归到这。我去复习C语言了。还有10天考试。加油!!!
下面是
<conio.h>包含的常用函数:
cgets(char*);;

cputs(constchar*);

cscanf(constchar*,...);

inpw(unsignedshort);

getch(void);

getche(void);

kbhit(void);

outp(unsignedshort,int);

outpw(unsignedshort,unsignedshort);

putch(int);

ungetch(int);

void_Cdeclclreol(void);

void_Cdeclclrscr(void);

void_Cdecldelline(void);

int_Cdeclgettext(intleft,inttop,intright,intbottom,void*destin);

void_Cdeclgettextinfo(structtext_info*r);

void_Cdeclgotoxy(intx,inty);

void_Cdeclhighvideo(void);

void_Cdeclinsline(void);

void_Cdecllowvideo(void);

int_Cdeclmovetext(intleft,inttop,intright,intbottom,intdestleft,intdesttop);

void_Cdeclnormvideo(void);

int_Cdeclputtext(intleft,inttop,intright,intbottom,void*source);

void_Cdecltextattr(intnewattr);

void_Cdecltextbackground(intnewcolor);

void_Cdecltextcolor(intnewcolor);

void_Cdecltextmode(intnewmode);

int_Cdeclwherex(void);

int_Cdeclwherey(void);

void_Cdeclwindow(intleft,inttop,intright,intbottom);

char*_Cdeclcgets(char*str);

int_Cdeclcprintf(constchar*format,...);

int_Cdeclcputs(constchar*str);

int_Cdeclcscanf(constchar*format,...);

int_Cdeclgetch(void);

int_Cdeclgetche(void);

char*_Cdeclgetpass(constchar*prompt);

int_Cdeclkbhit(void);

int_Cdeclputch(intc);

int_Cdeclungetch(intch);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值