递归:汉诺塔

一、递归的思想

 

  1. 递归分为递推和回归两个过程
    以求一个数n的n!为例:
    递推:若路人A能帮我把(n-1)!求出来,那我只需要在此基础上乘n就行了 路人A会想,若路人B能帮我把(n-2)!求出来,那我只需要在此基础上乘(n-1)就行了。
    照这样执行下去,总有一个人的工作是只需要把1!求出来就行了,那这个非常简单,我们定义一下1!=1就可以了。
    回归:当有人把1!=1算出来之后,就要开始算2!了,然后开始3!,知道n!,这个过程就称为回归。
     
  2. 递归不能无休止地执行下去,要有一个结束的标志
    如:
 def recursion():
     recursion()

 

        这种递归是毫无意义的,因为缺少递归完成的条件。等编译器执行到设置最大递归次数后就会出现异常。

        在上一个例子中,定义1!=1就是递归完成的条件。

二、递归的几个例子

 

  1.    求数n的阶乘n!
    首先在没有学习递归之前我们可以使用迭代的方法去完成,代码如下:
def fact(n):
    result = n
    for i in range(1,n):
        result *= i
    return result
number = int(input('请输入一个数:'))
result = fact(number)
print("%d的阶乘为: %d"%(number,result))

        学习了递归可以使用递归方法,代码如下:

def fact_recursion(n):
    if n == 1:
        return 1
    return n*fact_recursion(n-1)
number = int(input('请输入一个数:'))
result = fact_recursion(number)
print("%d的阶乘为: %d"%(number,result)

2.  求菲波那切数列

注意在斐波那契数列中用到了两个自我调用,所以会需要两个初始值(或者称为完成条件),即:f(1)=f(2)=1

代码如下:

def febnaqie(n):
    if n == 1 or n == 2:
        return 1
    return febnaqie(n-1)+febnaqie(n-2)
for i in range(1,13):
    print(febnaqie(i))

实际上递归的实现时非常浪费时间的,当递归层数逐渐变大时,计算速度所需时间会变得很长,而迭代会非常省时:

def fibb(n):
    a,b = 0,1
    for i in range(1,n+1):
        a,b =b,a+b  #注意此处采用的这种赋值法,是先进行右边计算在进行赋值,不能用a = b 然后再b = a+b
	print(a)
fibb(12)
1
1
2
3
5
8
13
21
34
55
89
144

3.  求解汉诺塔问题

代码如下:

def hanoi(n,x,y,z):#x为起始位置(柱子),y为借用的柱子,z为目的位置
    if n == 1:
        print(x,'-->',z)#结束的条件,也就是递推到最后一步时最后一个人做的工作
    else:
        hanoi(n-1,x,z,y)#第一步,有人将n-1个圆盘从x借助z移动到y柱子上
        print(x,'-->',z)#第二步,我将最后一个圆盘从x柱子移动到z柱子上
        hanoi(n-1,y,x,z)#第三步,有人将n-1个圆盘从y柱子借助x柱子移动到z柱子上
hanoi(3,'x','y','z')

注意代码中的第一步第三步均使用自身定义的函数完成。

执行效果展示如下:

三、递归和迭代的区别

观察上面那段 求数n的阶乘n! 的代码,我们发现:

迭代:使用的是循环结构;不需要调用函数和占用额外内存

递归:使用的是选择结构;能使程序的结构更清晰、简介,更容易让人读懂;缺点是耗费运行时间和内存

四、计算机是如何实现递归的

计算机在执行递归时分为前行和退回两个阶段,退回顺序是它前行顺序的逆序。在退回过程中,可能要执行某些动作,包括恢复在前行过程中存储起来的某些数据。

这种存储和恢复方式,显然符合栈这种数据结构。因此编译器使用实现递归操作

要想真正理解递归,上面这段话非常重要!!!

递归在不断判断的过程其实是一个压栈的过程,当条件判断结束时,计算机会自动执行出栈,将之前计算得到的结果一个个拿出来用于计算。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值