一、递归函数
定义:
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
我们来举个例子吧,比如:有个人问“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
注意:二分法查找非常快且非常常用,二分法查找的前提必须待查找的序列是一个有序的。