zoukankan      html  css  js  c++  java
  • 递归调用

    def fact(n):
        if n == 1:
            return 1
        return n * fact(n-1)
    print(fact(1))
    print(fact(5))
    print(fact(100))
    #递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
    #使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000):
    #print(fact(1000)) 这一句会出现错误,递归实际上是在栈中进行的,栈空间有限,因而递归次数不能太多
    #解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
    #尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
    def fact2():
        return fact_iter(n, 1)
        
    def fact_iter(Inum, product):
        if num = 1:
            return product
        return fact_iter(num-1, num * product)

    可以看到,return fact_iter(num - 1, num * product)仅返回递归函数本身,num - 1num * product在函数调用前就会被计算,不影响函数调用。

    fact(5)对应的fact_iter(5, 1)的调用如下:

    ===> fact_iter(5, 1)
    ===> fact_iter(4, 5)
    ===> fact_iter(3, 20)
    ===> fact_iter(2, 60)
    ===> fact_iter(1, 120)
    ===> 120
    

    尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

    遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

  • 相关阅读:
    Android Studio生成APK自动追加版本号
    jquery.nicescroll.min.js滚动条使用方法
    Guid.NewGuid().ToString()生成唯一码js
    解决移动端H5海报滑动插件适应大部分手机问题 手机端高度自适应
    SouthidcEditor编辑器如何支持上传png图片
    谈灰色行业网站建设需要注意的事项
    33个免费的电子商务图标集
    WebKit的已实施srcset图像响应属性
    免费清新浅色图标集
    闪光的不一定是金子:设计数据的一种常见误解
  • 原文地址:https://www.cnblogs.com/rain-1/p/5540383.html
Copyright © 2011-2022 走看看