Hanoi Tower 经典递归题目之汉诺塔的简单解析
2011-11-14
Hashtable和HashMap采取的hash/rehash算法都概略一样,所以机能不会有很大年夜的不合。
恶徒也熟悉真谛,只是他见了真谛就胆怯。 当然、这是一个经典的递归题目~
想必来看这篇博文的同窗对汉诺塔应当不会陌生了吧,
只有受过教导的诚恳至心的人才是有趣味的人,也只有他们才是社会所须要的。如许的人越多,天堂来到人世也就越快。 写这篇博还是有初志的:
之前学数据布局的时辰本身看书、也上彀上查了很多材料,材料都斗劲散、并且描述的不是很清楚,对于当时方才
接触算法的我,要完全懂得还是有必然难度。今天正好有时候就收拾了下思路、重写解析了一下之前的困惑的处所、
没有透辟的处所便都豁然开朗了。所以火烧眉毛把我的设法记录下来,和大师分享。
若是你也是和之前的我一样对hanoi tower没能完全消化,或者方才接触汉诺塔,那我的这种懂得体式格式能给你些
许帮助,若是你感觉已经完全把握的斗劲坚固了,那也可以看看,有好的idea可以一路分享;毕竟成果交换评论辩论也是一种很好的
进修体式格式。
好了,空话不久不多说,切入正题。
关于汉诺塔来源啊、传说啊神马的就不烦琐了,我们直接切入正题:
题目描述:
有一个梵塔,塔内有三个座A、B、C,A座上有诺干个盘子,盘子大小不等,大的鄙人,小的在上(如图)。
把这些个盘子从A座移到C座,中心可以借用B座但每次只能容许移动一个盘子,并且在移动过程中,3个座上的盘
子始终对峙大盘鄙人,小盘在上。
描述简化:把A柱上的n个盘子移动到C柱,此中可以借用B柱。
我们直接假设有n个盘子:
先把盘子从小到大标识表记标帜为1、2、3......n
先看原题目三个柱子的状况:
状况0 A:按次序堆放的n个盘子。B:空的。C:空的。
目标是要把A上的n个盘子移动到C。因为必须大的鄙人小的在上,所以终极成果C盘上最下面的应当是标号为n的盘子,试想:
要取得A上的第n个盘子,就要把它上方的n-1个盘子拿开吧?拿开放在哪里呢?共有三个柱子:A显然不是、若是放在C上
了,那么最大的盘子就没处所放,题目还是没获得解决。所以选择B柱。当然,B上方也是遵守大鄙人小在上的原则堆放的
(记住:先不要管具体如何移动,可以算感化一个函数完成移动,如今不消去推敲函数如何实现。这点很首要)。
很明显:上一步完成后三个塔的状况:
状况1: A:只有最大的一个盘子。B:有按规矩堆放的n-1个盘子。C空的。
上方的很好懂得吧,好,其实到这里就已经完成一半了。(若是前面的没懂,请重看一遍。point:不要管如何移动!)
我们持续:
这时辰,可以直接把A上的最大盘移动到C盘,移动后的状况:
中心状况: A:空的。B:n-1个盘子。C:有一个最大盘(第n个盘子)
要重视的一点是:这时辰的C柱其实可以看做是空的。因为剩下的所有盘子都比它小,它们中的任何一个都可以放在上方,也就是 C柱上。
所以如今三个柱子的状况:
中心状况: A:空的。B:n-1个盘子。C:空的
想一想,如今的题目和原题目有些类似之处了吧?。。如何更类似呢?。显然,只要吧B上的n-1个盘子移动到A,待解决的题目和原题目就比拟就只是范围变小了
如今推敲如何把B上的n-1个盘子移动到A上,其实移动办法和上文中的把n-1个盘从A移动到B是一样的,只是柱子的名称换了下罢了。。(若是写成函数,只是参数调用次序改变罢了)。
假设你已经完成上一步了(同样的,不要推敲如何去移动,只要想着用一个函数实现就好),请看如今的状况:
状况2: A:有按次序堆放的n-1个盘子。B:空的。C:按次序堆放的第n盘子(可看为空柱)
就在刚才,我们完美的完成了一次递归。若是没看懂请从新看一遍,可以用笔画出三个状况、静下心来慢慢推理。
我几回再三夸大的:当要把最大盘子上方的所有盘子移动到另一个空柱上时,不要关怀具体如何移动,只用把它看做一个函数可以完成即可,不消关怀函数的具体实现。若是你的思路纠结在这里,就很难持续深切了。
到这里,其实 根蒂根基思路已经理清了。状况2和状况0,除了范围变小 ,其它方面没有任何差别了。然后只要用雷同的思维体式格式,就能往下深切。。。
好了,看看如何用算法实现吧:
定义函数Hanoi(a,b,c,n)默示把a上的n个盘子移动到c上,此中可以用到b。
定义函数move(m,n)默示把m上的盘子移动到n上
我们须要解决的题目恰是 Hanoi (a,b,c,n) //上文中的状况0
1、把A上的n-1个移动到B: Hanoi (a,c,b,n-1); // 操纵停止为状况1
2、把A上的大盘子移动到C move(a,c)
3、把B上的n-1移动到A Hanoi (b,c,a,n-1); //操纵停止位状况2(和状况1比拟只是范围变小)
若是如今还不克不及懂得、请回过火再看一遍、毕竟成果若是是初学者不是很轻易就能懂得的。可以用笔记下几个关键的状况,并且看看你有没有真正的投入去看,自力去思虑了。
给出算法C代码:
main()
{
int n;
printf("请输入数字n以解决n阶汉诺塔题目: ");
scanf("%d",&n);
hanoi(n,""A"",""B"",""C"");
}
void hanoi(char A,char B,char C,int n)
{
if(n==1)
{
printf("Move disk %d %c to %c ",A,C,n);
}
else
{
hanoi(A,C,B, n-1);
printf("Move disk %d %c to %c ",n,A,C);
hanoi(B,A,C,n-1,);
}
}
//以上代码c-free5编译经由过程。
//代码出处:http://www.cnblogs.com/yanlingyin/ 一条鱼~
以上、若是有不合错误的处所、还您能指出。
我对递归的一点懂得:
解决实际题目时、不克不及太去关怀实现的细节(因为递归的过程恰好是我们实现的办法)就像这个题目,如在第一步就过多的纠结于如何把n-1个盘子移动到B上、那么你的思路就很难持续深切。只要看做是用函数实现就好,若是你能看出不管怎么移动,其实本质都一样的时辰,那么就能较快的获得成果了。就像这个案例,要重视到我们做的关键几步都只是移动的次序有改变,此中的规矩没有改变,如
若是用函数默示的话,就只是参数调用的次序有所不合了。在递归的应用中、不消关怀每一步的具体实现 ,只要看做用一个函数默示就好。解析题目的时辰,最好画出本身的推理过程,获得有效的状况图。
思虑题目讲求思路的连贯性、力求尽快进入状况,享受完全投入到一件事中的美好感触感染。
【原创作品】转载请注明出处http://www.cnblogs.com/yanlingyin/
一条鱼~ 博客园
威尔逊