zoukankan      html  css  js  c++  java
  • Python学习札记(十四) Function4 递归函数 & Hanoi Tower

    reference:递归函数

    Note

    1.在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

    eg.计算阶乘:

    #!/usr/bin/env python3
    
    def my_func(n) :
    	if n == 1 :
    		return 1
    	return n * my_func(n-1)
    

    output:

    >>> from function4 import my_func
    
    >>> my_func(1)
    1
    
    >>> my_func(2)
    2
    
    >>> my_func(3)
    6
    
    >>> my_func(4)
    24
    
    >>> my_func(5)
    120
    
    >>> my_func(10)
    3628800
    
    

    递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

    func(5)的计算过程:

    ===> func(5)
    ===> 5 * func(4)
    ===> 5 * (4 * func(3))
    ===> 5 * (4 * (3 * func(2)))
    ===> 5 * (4 * (3 * (2 * func(1))))
    ===> 5 * (4 * (3 * (2 * 1)))
    ===> 5 * (4 * (3 * 2))
    ===> 5 * (4 * 6)
    ===> 5 * 24
    ===> 120
    

    2.使用递归函数需要注意 防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

    eg. my_func(1000)

    output:

      File "/Users/wasdns/Desktop/Python-Learning/function/function4.py", line 4, in my_func
        if n == 1 :
    RecursionError: maximum recursion depth exceeded in comparison
    

    3.解决递归调用栈溢出的方法是进行尾递归优化:

    尾递归是指:1.在函数返回的时候,调用自身本身;2.return语句不能包含表达式。

    这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

    也就是说,尾递归优化重复调用一个帧栈,节省了大量运行时栈空间。

    eg.

    def my_func_2(num, product) :
    	if num == 1 :
    		return product
    	return my_func_2(num-1, num*product)
    

    output:

    >>> my_func_2(5, 1)
    120
    

    计算过程:

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

    练习

    Hanoi Tower解法请参考:Hanoi Tower

    抽象步骤:

    1.将A柱中n-1个柱子搬到B柱。

    2.将A柱中第n个柱子搬到C柱。

    3.将A柱视作B柱,B柱视作A柱,重复上述两个步骤。

    一个思考问题的关键是,忽略细节。在思考的时候,需要把函数视作一个整体功能,即将n个盘子从a移动到b,忽略其细节对于思考是一件很重要的事情。

    def move(n, a, b, c) :
    	if (n == 1) :			# A move last one to C
    		print(a, '=>', c)
    		return
    	else :
    		move(n-1, a, c, b)	# from A move n-1 to B 
    		move(1, a, b, c)	# A move last one to C
    		move(n-1, b, a, c)	# from B move n-1 to C
    
    >>> move(3, 'A', 'B', 'C')
    A => C
    A => B
    C => B
    A => C
    B => A
    B => C
    A => C
    

    2017/2/3

  • 相关阅读:
    Android推送服务——百度云推送
    关于HierarchyViewer的使用
    Android开发者的演示工具——asm.jar
    重装huson遇到的一些错误及解决
    对比语法错误、语义错误以及运行时错误
    对比常量存储与堆栈
    php下载文件夹目录下的文件
    B/S(WEB)系统中使用Activex插件调用扫描仪实现连续扫描并上传图像(IE文件扫描并自动上传
    上传文件夹
    如何在Web页面里使用高拍仪扫描上传图像
  • 原文地址:https://www.cnblogs.com/qq952693358/p/6362808.html
Copyright © 2011-2022 走看看