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

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

 

posted @ 2017-04-15 15:41  Michael--chen  阅读(390)  评论(0编辑  收藏  举报