zoukankan      html  css  js  c++  java
  • 【算法】递归

     递归

    实例:在盒子中寻找钥匙

    方法1:使用while循环

    算法

    (1) 创建一个要查找的盒子堆。

    (2) 从盒子堆取出一个盒子,在里面找。

    (3) 如果找到的是盒子,就将其加入盒子堆中,以便以后再查找。

    (4) 如果找到钥匙,则大功告成!

    (5) 回到第二步。

    代码
    def look_for_key(main_box):
        pile=main_box.make_a_pile_to_look_through()
        while pile is not empty:
            box=pile.grap_a_box
            for item in box:
                if item.is_a_box():
                    pile.append(item)
                elif item.is_a_key():
                    print('found a key')
    

      

    方法2:使用递归

    算法

    (1) 检查盒子中的每样东西。

    (2) 如果是盒子,就回到第一步。

    (3) 如果是钥匙,就大功告成!

    代码
    def look_for_key(box):
        for item in box:
            if item.is_a_box():
                look_for_key(item)  #递归
            elif item.is_a_key():
                print('found a key')
    

      

    如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。如何选择要看什么对你来说更重要。

    基线条件和递归条件

    编写递归函数时,必须告诉它何时停止递归。否则会导致无限循环。

    递归函数两部分

    基线条件(base case)和递归条件(recursive case)

    递归条件:指的是函数调用自己
    基线条件:指的是函数不再调用自己,从而避免形成无限循环。
    示例
    def countdown(i):
        print(i)
        if i<=0:                       #基线条件
           return 
        else:                          #递归条件
            countdown(i-1)
     
    print(countdown(4))
    

      

    定义

    栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。

    特点

    LIFO,即后进先出(Last in, first out)

    调用栈(call stack)

    计算机在内部使用被称为调用栈的栈。

    示例
    def greet2(name):
        print("how are you," + name + "?")
    def bye():
        print('ok bye!')
     
    def greet(name):
        print('hello,'+name+'!')
        greet2(name)
        print('getting ready to say bye..')
        bye()
    
    print(greet('lilip'))
    

      

    调用过程

    1. 调用greet(‘lilip’),首先为该函数调用分配一块内存
    2. 打印,hello,lilip!
    3. 调用greet2(‘lilip’),接着为这个函数调用分配一块内存
    4. 计算机使用一个栈表示这些内存块,其中第二个内存块位于第一个内存块的上面。
    5. 打印,how are you,lilip?greet2函数运行完毕,然后从函数调用返回。此时,栈顶的内存块被弹出。
    6. 栈顶内存块是函数greet,返回到函数greet。
    7. 打印getting ready to say bye..
    8. 调用bye()函数,栈顶添加函数bye的内存块
    9. 打印,ok bye!并从这个函数返回。
    10.  返回到函数greet,此时运行完毕。从函数greet返回,

    调用另一个函数时,当前函数暂停并处于未完成状态。该函数的所有变量的值都还在内存中

    这个栈用于存储多个函数的变量,被称为调用栈。

    递归调用栈

    递归函数也使用调用栈!

    示例

    阶乘递归函数

    def fact(x):
        if x==1:
            return 1
        else:
            return x*fact(x-1)
     
    print(fact(3))
    

      

    调用过程

    代码

    调用栈

    备注

    fact(3)

    fact

    x

    3

    第一次调用fact

    x=3

    if x==1:

    fact

    x

    3

    else:

    fact

    x

    3

    return x*fact(x-1)

    fact

    x

    2

    fact

    x

    3

    递归调用

    if x==1:

    fact

    x

    2

    fact

    x

    3

    现在位于对fact的第二次调用中

    x=2

    最上面的函数调用是当前所处的调用

    else:

    fact

    x

    2

    fact

    x

    3

    两个函数调用都有变量x,但这些x变量的值不同

    return x*fact(x-1)

    fact

    x

    1

    fact

    x

    2

    fact

    x

    3

    在栈顶层调用中,不能访问下面其他内存块调用的x变量,反之亦然

    if x==1:

    fact

    x

    1

    fact

    x

    2

    fact

    x

    3

    return 1

    fact

    x

    1

    fact

    x

    2

    fact

    x

    3

    从栈中弹出第一个方块,意味着将从这个调用返回,返回1

    return x*fact(x-1)

    fact

    x

    2

    fact

    x

    3

    x为2

    fact(x-1)返回1

    最终返回2

    return x*fact(x-1)

    fact

    x

    3

    x为3

    fact(x-1)返回2

    最终返回6

    注意:

    1. 每个fact调用都有自己的x变量。在一个函数调用中不能访问另一个的x变量。
    2. 每个函数调用都要占用一定的内存,如果栈很高,就意味着计算机存储了大量函数调用的信息。

    小结

    • 递归指的是调用自己的函数。
    • 每个递归函数都有两个条件:基线条件和递归条件。
    • 栈有两种操作:压入和弹出。
    • 所有函数调用都进入调用栈。
    • 调用栈可能很长,这将占用大量的内存。
  • 相关阅读:
    linux 运维 nginx服务器
    linux 运维,代理,acl控制访问
    shell脚本 awk工具
    shell脚本 sed工具
    shell脚本 字串截取 正则表达式
    Django ORM 反向查询
    Django model操作
    Form的is_valid校验规则及验证顺序
    Django 中的Form、ModelForm
    Django 中的Form表单认证
  • 原文地址:https://www.cnblogs.com/lilip/p/9515186.html
Copyright © 2011-2022 走看看