zoukankan      html  css  js  c++  java
  • 13-函数递归

    一、递归的定义

    函数的递归调用:是函数嵌套调用的一种特殊形式

    具体是指:

        在调用一个函数的过程中又直接或者间接地调用到本身

    # 直接调用本身
    def f1():
        print('是我是我还是我')
        f1()
    f1()

    # 间接接调用本身
    def f1():
        print('===>f1')
        f2()
    
    def f2():
        print('===>f2')
        f1()
    
    f1()

    # 一段代码的循环运行的方案有两种
    # 方式一:while、for循环
    while True:
        print(1111)
        print(2222)
        print(3333)
    
    # 方式二:递归的本质就是循环:
    def f1():
        print(1111)
        print(2222)
        print(3333)
        f1()
    f1()

    二、递归的结束

    递归调用不应该无限地调用下去,必须在满足某种条件下结束递归调用

    n=0
    while n < 10:                   # 设置循环结束条件
        print(n)
        n+=1
    
    def f1(n):
        if n == 10:                 # 设置递归结束条件
            return
        print(n)
        n+=1
        f1(n)
    
    f1(0)

    补充:

    '''
    1. 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可以使用
    sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制
    
    2. python不是一门函数式编程语言,无法对递归进行尾递归优化。
    '''

    三、递归的两个阶段

    回溯:一层一层调用下去

    递推:满足某种条件,结束递归,然后一层一层返回

    # salry(4) = age(3) + 1000
    # salry(3) = age(2) + 1000
    # salry(2) = age(1) + 1000
    # salry(1) = 5000
    
    def salary(n):
        if n == 1:
            return 5000
        return age(n-1) + 1000
    
    res=age(4)
    print(res)                  # 8000

    四、递归应用

    4.1 嵌套列表的取值(计算文件夹大小也可这么操作):

    l=[1,2,[3,[4,[5,[6,[7,[8,[9,10,11,[12,[13,]]]]]]]]]]
    
    def f1(list1):
        for x in list1:
            if type(x) is list:
                # 如果是列表,应该再循环、再判断,即重新运行本身的代码
                f1(x)
            else:
                print(x)
    
    f1(l)

    4.2 斐波拉契数列

    法一:函数递归得到第n项斐波拉契数列,循环函数得到数列

    def print_Fibonacci(n):
        for i in range(1,n+1):
            print(Fibonacci(i),end=" ")
        print()
    
    def Fibonacci(n):
        if n == 1 or n == 2:
            return n-1
        elif n > 2:
            return Fibonacci(n-2) + Fibonacci(n-1)
        return -1
    
    print(Fibonacci(15))
    print_Fibonacci(15)

    法二:设定数列初始的两个值与数列终止值,每次替换初始值为平移一个单位后的两个值,并打印

    def fib(a,b,c):
        if a > c:
            return
        print(a,end=" ")
        fib(b,a+b,c)
    fib(0,1,388)

    法三:非递归方法实现

    def fib2(max):
        a=0
        b=1
        while a< max:
            yield a
            a, b=b, a+b
    g = fib2(500)
    for i in g:
        print(i,end=" ")

    4.3 汉诺塔

    def hannuota(n,A="A",B="B",C="C"):
        if n == 1:
            print(f"将第{n}块积木从{A}柱放到{C}柱")
            return
        hannuota(n-1,A,C,B)
        print(f"将{n}块积木从{A}柱子放到{C}柱子")
        hannuota(n-1,B,A,C)
    
    n = input("请输入汉诺塔层数:")
    
    if n.isdigit():
        n = int(n)
        hannuota(n)
    else:
        print("请输入数字")

    五、查找与排序

    5.1 二分法

    算法:是高效解决问题的办法
    算法之二分法

    需求:有一个按照从小到大顺序排列的数字列表
    需要从该数字列表中找到我们想要的那个一个数字
    如何做更高效???

    方案一:整体遍历---效率太低

    for num in nums:
        if num == find_num:
            print('find it')
            break

    方案二:二分法

    思路:

    def binary_search(find_num,列表):
        mid_val=找列表中间的值
        if find_num > mid_val:
            # 接下来的查找应该是在列表的右半部分
            列表=列表切片右半部分
            binary_search(find_num,列表)
        elif find_num < mid_val:
            # 接下来的查找应该是在列表的左半部分
            列表=列表切片左半部分
            binary_search(find_num,列表)
        else:
            print('find it')

    实现:

    nums=[-3,4,7,10,13,21,43,77,89]
    find_num=8
    def binary_search(find_num,l):
        print(l)
        if len(l) == 0:
            print('找的值不存在')
            return
        mid_index=len(l) // 2
    
        if find_num > l[mid_index]:
            # 接下来的查找应该是在列表的右半部分
            l=l[mid_index+1:]
            binary_search(find_num,l)
        elif find_num < l[mid_index]:
            # 接下来的查找应该是在列表的左半部分
            l=l[:mid_index]
            binary_search(find_num,l)
        else:
            print('find it')
    
    binary_search(find_num,nums)

    5.2 快速排序

    l = [12,5,48,99,37,26,0,7,51]
    
    def Sort(l,low,high):
    flag = l[low] i = low j = high # 若i<j 则需要继续找flag位置,并递归 if i < j: # 循环查找,直到i=j,找到flag位置 while i < j: while i < j and l[j] >= flag: j -= 1 if i < j: l[i] = l[j] i += 1 while i < j and l[i] <= flag: i += 1 if i < j: l[j] = l[i] j -= 1 l[i] = flag # if i == low: # # Sort(l,low,i-1) # Sort(l,i+1,high) # elif i == high: # Sort(l,low,i-1) # # Sort(l, i + 1, high) # else: # Sort(l,low,i-1) # Sort(l, i+1, high) if low < i -1: # 若 low < i-1 则至少还有两个元素,继续进行排序。若只有一个则不再进入递归,开始往回递推 Sort(l,low,i-1) if high > i+1: # 同上 Sort(l, i + 1, high) print(l[0]) Sort(l,0,len(l)-1) print(l)
  • 相关阅读:
    如何在一个控件上同时实现单触和多触事件
    看看iOS 5.0 beta 6都有哪些变化吧
    转,net实现下载
    转检测到潜在危险
    如何分析已有项目如何能够得到最快最大的提升???
    转Unity 入门
    近段总结
    转,net几个热点问题
    dll动态链接库
    转使用NUnit在.Net编程中进行单元测试
  • 原文地址:https://www.cnblogs.com/zhubincheng/p/12570689.html
Copyright © 2011-2022 走看看