汉诺塔 经典递归算法 in python

时间:2021-08-04 09:54:35

    递归算法,把大规模问题分解成容易解决而且求解方法相同的子问题,一般用递归函数实现,递归函数就是不断调用自身的函数。

    举个例子:

            汉诺塔 经典递归算法 in python

      俄罗斯套娃(应该都玩过,里面最小的那个不能打开,其他能打开。从最小的娃娃开始,用稍大的那个娃娃套着,直至最大的一个套住所有的娃娃)。

     现在有如图俄罗斯套娃,已经按正确的方法套好,里面最小的那个娃娃背上写了一个密码。现在需要求解的问题是得到那个密码,并且得到密码后要把这套俄罗斯娃娃按正确的方法套好。

      那么做法应该是,一层一层地打开娃娃,直到看到最小的娃娃之后获取密码,然后一个一个的把娃娃合上。也就是,分别按顺序对每一个娃娃进行打开的操作,直至打开到小娃娃,查看密码,然后再进行依次闭合娃娃的操作。

      这就是一个递归过程。而这个递归函数就是打开闭合娃娃,判断里面的娃娃是否是最小的那个,如果是,获取密码,如果不是,打开下一个娃娃,并且最后关闭当前娃娃。

     

伪代码如下:

# 娃娃编号从小到大依次递增,为1~5
def getKey ( n ) :
	if n == 1 :   # 判断当前娃娃是不是最小的那个娃娃
		读取密码   #进行操作
	else :
		getKey(n-1)   # 对当前娃娃套住的娃娃进行相同的操作 
		关闭娃娃      <span style="font-family: Arial, Helvetica, sans-serif;">#进行操作</span>


一个问题能否用递归求解,要看这个问题能不能逐层分解成一个个规模依次变小的小问题,同时有能够进行判断的下限(就是不能再小的子问题)。


而确定能够用递归过程求解之后,关于求解步骤,可以直接分析最小的子问题跟比最小子问题“大1”的子问题。还需要知道的有:最小子问题的判断依据以及处理步骤、如何递归调用自身。

       拿汉诺塔问题举例:(借助B柱,将A柱上的n块盘子移动到C柱)

汉诺塔 经典递归算法 in python

       最小的子问题就是:将一块盘子从A移动到C柱

“大1”的子问题是:将两块盘子从A移动到C柱,不妨在草稿纸上画个图,显然有三个步骤:

1.将最上面的盘子从A移动到B

2.将A下面的盘子从A移动到C

3.将B上的盘子移动到C

而程序调用自身则是逐次对(n-1)个盘子进行同样的操作就可以解决n个盘子移动的问题。

只需以上三步分析就能得到这个递归程序的全部求解过程。


汉诺塔代码如下:

n = int(input("输入初始化时A塔上盘子的个数n:\n"))
def move( n , A , B ,C ):   
	if n == 1 :       
		print( "%s is moved to %s" %(A ,C) )
	else :
		move( n-1 , A , C , B )   
		move( 1 , A , B , C )
		move( 1 , B , A , C )
move( n ,'A' , 'B' , 'C')	


如果还是不理解的话,自己动手写一个递归程序最能加深理解。经典的递归问题有:Fibonacci数列、扫雷小游戏。    

题外话:传说古老印度在一个圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片圣庙,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片,一次只移动一片,不管在哪根针上,小片必在大片上面。当所有的金片都从梵天穿好的那根针上移到另外一概针上时,世界就将在一声霹雳中消灭,梵塔、庙宇和众生都将同归于尽。

    n个盘子最少需要移动2^n-1,如果一秒钟移动一次,计算出来需要5800多亿年,那时候,地球还存在吗?这样看来,这个毁灭论倒是有一定道理的啊。