zoukankan      html  css  js  c++  java
  • Python基础之递归函数与二分法

      一、递归函数

      定义:

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

      我们来举个例子吧,比如:有个人问“egon”年龄,他说比“小大”大5岁,“小大”又说比“小保”大5岁,“小保”又说

    比“小健”大5岁,最后,“小健”又问我,我又比“小健”小5岁。已知我今年20岁,求“egon”今年多少岁?

      分析:看到这个题,我们首先可以发现这中间有一个规律,就是问的这几个人彼此间年龄的差距正好是5岁,既然,

    有了这个规律,就好办了。在看一共问了几个人,就可以得出“egon”的年龄了。

      用代码表示如下:

    def age(n): #形参n表示问的人数
        if n == 1 : #当"n==1"时,即返回我的年龄20
            return 20
        else:
            return age(n-1)+5 #每问一个人,加5岁
    print(age(5)) #打印"egon"的年龄,已知他问了4个人,"小大"、"小保"、"小健"、"我"加上“egon”自己共5个人
    -----------------输出结果-------------------
        40 #得出"egon"的年龄
    

      下面我们就用图来看看具体的流程吧!

      递归函数的特点:

        1、调用自身函数;

        2、有一个明显的结束条件,问题规模相比上次递归有所减少。

      递归函数的优点:

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

       递归函数的缺点:

        递归的效率不高,递归层次过多会导致栈溢出,默认的栈大概是1000层。

      注意:

      使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个

    函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数

    过多,会导致栈溢出。

      二、二分法

       二分法是一种快速查找的方法,复杂度低,逻辑简单易懂,总的来说就是不断的除以2除以2...不断缩小范围,快速

    查找想要的元素。

      下面我们还是来举例说明吧!

      已知data是一个按升序排列的列表,我们要查看一个元素是否在列表中。

      data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]

      代码如下:

    #定义递归函数阶段
    def search(num,data): #用递归函数使用二分法
        da_index = int(len(data)/2)
        da_values = data[da_index]
        if len(data) > 1: #要data的长度大于1时,防止最后只剩一个元素的特殊情况
            if da_values > num : #当中间的值大于num的时候
                data = data[:da_index] #我们就要取列表中间往左边所有值的范围
                return search(num,data) #返回切后的列表给函数,继续查找元素
            elif da_values < num : #当中间的值小于num的时候
                data = data[da_index:] #我们就要取列表中间往右边所有值的范围
                return search(num,data) #返回切后的列表给函数,继续查找元素
            else: #不大不小就正好是要找的元素
                print("已找到%s,在data中"%num)
                return
        else:#因为是二分查找,特别是列表两头的元素,就会容易出现之下一个的情况
            if data[0] == num : #只剩下一个元素的时候,判断是否为要查的元素
                print("已找到%s,在data中"%num)
            else: #不是就走下面的代码
                print("Sorry,data中没有这个元素:%s"%num)
    #调用函数阶段
    search(18,data) #调用函数,查找18是否在data中
    search(1,data) #调用函数,查找1是否在data中,元素在列表最开头位置
    search(35,data) #调用函数,查找35是否在data中,元素在列表最末尾位置
    search(56,data) #调用函数,查找56是否在data中
    -----------------------输出结果----------------------------
    已找到18,在data中
    已找到1,在data中
    已找到35,在data中
    Sorry,data中没有这个元素:56

      我们在来一个无序的元组,来查找一下里面是否有我们需要的元素在里面。好了,小二上菜:

      t = ("a","i","j","d","l","f","g","h","b","c","k","e")

      代码如下:

    #定义递归函数阶段
    def search(letter,t): #用递归函数使用二分法
        t_index = int(len(t)/2) #加上int得到元组中间索引值的整数
        if len(t) > 0: #元组的长度大于0时,走下面代码
            if letter in t[t_index]: #当要查的元素和中间索引值的元素对应的时候,则判断找到
                print("已找到 %s,在元组t中"%letter) #打印输出结果
                return #结束函数
            elif letter not in t[t_index:]: #当要查的元素没有在右边元组里的时候
                t = t[:t_index] #重新定义选定的范围在中间索引值的左边的元组
                return search(letter,t) #结束函数,返回得到结果,重新调用函数
            elif letter not in t[:t_index]: #当要查的元素没有在左边元组里的时候
                t = t[t_index:] #重新定义选定的范围在中间索引值的右边的元组
                return search(letter,t) #结束函数,返回得到结果,重新调用函数
        else: #当t长度为0的时候,说明里面没有值了,就说明要查的元素没在元组t中
            print("Sorry, t 中没有这个元素:%s" % letter) #打印输出结果
    #调用函数阶段
    search("j",t) #调用函数,查找"j"是否在t中
    search("a",t) #调用函数,查找"a"是否在t中,元素在最开头的位置
    search("e",t) #调用函数,查找"e"是否在t中,元素在最末尾的位置
    search("z",t) #调用函数,查找"z"是否在t中
    -----------------------输出结果---------------------
    已找到 j,在元组t中
    已找到 a,在元组t中
    已找到 e,在元组t中
    Sorry, t 中没有这个元素:z

      注意:二分法查找非常快且非常常用,二分法查找的前提必须待查找的序列是一个有序的。

  • 相关阅读:
    关于这个 blog
    P6499 [COCI2016-2017#2] Burza 题解
    CF1172F Nauuo and Bug 题解
    CF1479D Odd Mineral Resource 题解
    CF1442E Black, White and Grey Tree 题解
    CF1442D Sum 题解
    CF1025D Recovering BST 题解
    CF1056E Check Transcription 题解
    CF1025F Disjoint Triangles 题解
    红包算法的PHP实现
  • 原文地址:https://www.cnblogs.com/Michael--chen/p/6714395.html
Copyright © 2011-2022 走看看