• 递归


    递归

    一、什么是函数递归?

    函数的嵌套调用是:函数嵌套函数。函数的递归调用:它是一种特殊的嵌套调用,但是它在调用一个函数的过程中,又直接或间接地调用了它自身。

    
    
    def foo():
        print('from foo')
        foo()
    
    
    foo()  # 进入死循环
    

    如果递归函数不断地调用函数自身,那么这个递归函数将会进入一个死循环,因此我们应该给递归函数一个明确的结束条件。

    1.1 直接调用

    直接调用指的是:直接在函数内部调用函数自身。

    import sys
    
    print(f"最大递归层数: {sys.getrecursionlimit()}")
    最大递归层数: 3000
    import sys
    
    # 修改递归层数
    sys.setrecursionlimit(10000)
    
    
    def foo(n):
        print('from foo', n)
        foo(n + 1)
    
    
    foo(0)
    

    1.2 间接调用

    间接调用指的是:不在原函数体内调用函数自身,而是通过其他的方法间接调用函数自身。

    
    
    def bar():
        print('from bar')
        foo()
    
    
    def foo():
        print('from foo')
        bar()
    
    
    bar()
    

    递归必须要有两个明确的阶段:

    递推:一层一层递归调用下去,进入下一层递归的问题规模都将会减小
    2.
    回溯:递归必须要有一个明确的结束条件,在满足该条件开始一层一层回溯。

    递归的精髓在于通过不断地重复逼近一个最终的结果。

    ![53递归 - 代码.gif](http: // www.chenyoude.com / Python % E4 % BB % 8
    E % E5 % 85 % A5 % E9 % 97 % A8 % E5 % 88 % B0 % E6 % 94 % BE % E5 % BC % 83 / 53 % E9 % 80 % 92 % E5 % BD % 92 - % E4 % BB % A3 % E7 % A0 % 81.
    gif)

    '''
    ...
    age(5) = age(4) + 2
    age(4) = age(3) + 2
    age(3) = age(2) + 2
    age(2) = age(1) + 2
    age(1) = 26
    
    
    age(n) = age(n-1) +2 
    age(1) = 26  # n=1
    '''
    
    
    def age(n):
        if n == 1:
            return 26
        res = age(n - 1) + 2
        return res
    
    
    print(f"age(5): {age(5)}")
    age(5): 34
    

    二、为什么要用递归

    递归的本质就是干重复的活,但是仅仅是普通的重复,我们使用while循环就可以了。」

    lis = [1, [2, [3, [4, [5, [6, ]]]]]]
    
    
    def tell(lis):
        for i in lis:
            if type(i) is list:
                tell(i)
            else:
                print(i)
    
    
    # print(f"tell(lis): {tell(lis)}")
    tell(lis)
    1
    2
    3
    4
    5
    6
    

    三、如何用递归?

    3.1 二分法的应用

    有一个从小到大排列的整型数字列表,我们判断某一个数字是不是在这个列表里面。

    动图二分法查找数字23:

    ![53递归 - 二分23.gif](http: // www.chenyoude.com / Python % E4 % BB % 8
    E % E5 % 85 % A5 % E9 % 97 % A8 % E5 % 88 % B0 % E6 % 94 % BE % E5 % BC % 83 / 53 % E9 % 80 % 92 % E5 % BD % 92 - % E4 % BA % 8
    C % E5 % 88 % 8623.
    gif)

    动图二分法查找数字1:

    ![53递归 - 二分1.gif](http: // www.chenyoude.com / Python % E4 % BB % 8
    E % E5 % 85 % A5 % E9 % 97 % A8 % E5 % 88 % B0 % E6 % 94 % BE % E5 % BC % 83 / 53 % E9 % 80 % 92 % E5 % BD % 92 - % E4 % BA % 8
    C % E5 % 88 % 861.
    gif)

    nums = [1, 3, 7, 11, 22, 34, 55, 78, 111, 115]
    
    for item in nums:
        if item == 10:
            print('find it')
            break
    else:
        print('not exists')
    not exists
    

    对于上述的列表我们可能可以通过一个for循环实现我们需要的功能,但是当我们的列表中的元素个数非常多时,我们还用这种方法,那是极其复杂的,因此我们可以考虑使用二分法的思想实现。

    from random import randint
    
    nums = [randint(1, 100) for i in range(100)]
    nums = sorted(nums)
    print(nums)
    [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28,
     31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58,
     59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90,
     91, 91, 91, 94, 99, 99, 100]
    
    
    def search(search_num, nums):
        mid_index = len(nums) // 2
        print(nums)
        if not nums:
            print('not exists')
            return
        if search_num > nums[mid_index]:
            # in the right
            nums = nums[mid_index + 1:]
            search(search_num, nums)
        elif search_num < nums[mid_index]:
            # in the left
            nums = nums[:mid_index]
            search(search_num, nums)
        else:
            print('find it')
    
    
    search(7, nums)
    [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28,
     31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47, 51, 52, 52, 53, 53, 55, 55, 56, 56, 57, 57, 57, 58,
     59, 61, 62, 64, 66, 66, 67, 68, 69, 69, 71, 72, 72, 74, 74, 75, 76, 78, 78, 79, 79, 79, 79, 80, 82, 85, 88, 89, 90, 90,
     91, 91, 91, 94, 99, 99, 100]
    [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21, 21, 23, 24, 26, 26, 27, 28, 28,
     31, 33, 33, 34, 35, 38, 38, 39, 40, 42, 43, 45, 45, 46, 46, 47, 47]
    [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 10, 11, 11, 11, 11, 12, 13, 13, 15, 16, 16, 20, 21]
    [1, 2, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7]
    [6, 6, 7, 7, 7]
    find
    it
    

    四、练习

    '''
    2. 使用递归打印斐波那契数列,(前两个数的和得到第三个数,如:0 1 1 2 3 5 8...)
    '''
    
    # x = 0  # 1
    # y = 1  # 2
    # count = 0
    # while count < 10:
    #     print(x)  # 0,
    #     x, y = y, x + y
    #     count += 1
    # import sys
    # sys.setrecursionlimit(10)
    
    # def feibo(x, y, end=999):
    #     if x > end:
    #         return
    #
    #     print(x)
    #     x, y = y, x + y
    #     feibo(x, y)
    #
    #
    # feibo(0, 1)
    
    '''
    x = 0 # 1
    y = 1 -->  # 2
    x + y --> x # 3
    x + 2y --> x + y --> y
    '''
    
    '''
    一个嵌套很多层的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用递归取出所有的值
    '''
    
    l = [1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15]]]]]]]
    
    for i in l:
    
        if type(i) == list:
            for j in i:
                print(j)
        else:
            print(i)
    
    
    def get(lis):
        for i in lis:
            if type(i) == list:
                get(i)
            else:
                print(i)
    
    
    get(l)
    
    我把月亮戳到天上 天就是我的 我把脚踩入地里 地就是我的 我亲吻你 你就是我的
  • 相关阅读:
    转C#线程调用带参数的方法 ~
    转在本地计算机无法启动oracledbconsole服务。错误1053:服务没有及时响应启动或控制请求
    转对Oracle10修改机器名后服务无法启动的解决
    转Spring.net web.config配置文件(经过整理和修改)
    转C#修饰符
    IP地址比较方法
    [转贴]关于XmlDocument 和 XPathDocument
    javascript下调用正则表达式的方法
    bug小结
    SQL Cache Dependency
  • 原文地址:https://www.cnblogs.com/zhulipeng-1998/p/12863731.html
Copyright © 2020-2023  润新知