算法前戏----递归 二分查找 列表查找
一、递归
概念:
函数直接或者间接的调用自身算法的过程,则该函数称为递归函数。在计算机编写程序中,递归算法对解决一大类问题是十分有效的。
特点:
①递归就是在过程或者函数里调用自身。
②在使用递归策略时,必须有一个明显的结束条件,称为递归出口。问题规模相比上次递归有所减少,
③递归算法解题通常显得很简洁,但递归算法解题的效率较低。所以一般不倡导使用递归算法设计程序。
④在递归调用的过程当中系统的每一层的返回点、局部变量等开辟了栈来存储。递归函数次数过多容易造成栈溢出等。
所以一般不倡导用递归算法设计程序。
要求:
递归算法所体现的"重复"一般有三个条件:
①每次在调用规模上都有所缩小(通常是减半)。
②相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。
③在问题的规模极小时必须用直接解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),
无条件的递归调用将会成为死循环而不能正常结束。
分析以下函数的执行过程:
1 def func3(x): 2 if x>0: 3 print(x) 4 func3(x-1) 5 6 func3(5) 7 8 def func4(x): 9 if x>0: 10 func4(x-1) 11 print(x) 12 13 func4(5)
根据Python执行的过程,及函数调用去分析执行结果!
关于斐波拉契数列
斐波拉契数列指的是这样一个数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368。
特别注意:第0项是0,第1项是第一个1。这个数列从第2项开始,每一项都等于前两项之和。
1 def fibo(n): 2 before = 0 3 after = 1 4 if n == 0 or n == 1: 5 return n 6 7 if n <= 3: 8 return 1 9 return fibo(n-1)+fibo(n-2) 10 11 print(fibo(3))
二、二分查找
从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
特点:
二分查找算法就是不断将数组进行对半分割,每次拿中间元素和要找的元素进行比较。小就向右找,大就向左找!
要求:
在一段数字内,找到中间值,判断要找的值和中间值大小的比较。
如果中间值大一些,则在中间值的左侧区域继续按照上述方式查找。
如果中间值小一些,则在中间值的右侧区域继续按照上述方式查找。
直到找到我们希望的数字。
1 def search_data(data,data_find): 2 # 中间值的索引号的定义:数组长度/2 3 mid = int(len(data)/2) 4 # 判断从1开始的数字数组内查找 5 if data[mid] >= 1: 6 # 如果我们要找的值(data_find)比中间值(data[mid])小 7 if data[mid] > data_find: 8 print("你要找的数字比中间值[%s]小..." % data[mid]) 9 # 在中间值(data[mid])的左侧继续查找,在此函数中继续循环 10 search_data(data[:mid],data_find) 11 # 如果我们要找的值(data_find)比中间值(data[mid])大 12 elif data[mid] < data_find: 13 print("你要找的数字比中间值[%s]大..." % data[mid]) 14 # 在中间值(data[mid])的右侧继续查找,在此函数中继续循环 15 search_data(data[mid:],data_find) 16 else: 17 # 如果我们要找的值(data_find)既不比中间值(data[mid])大,也不比中间值(data[mid])小,则就是它 18 print("这就是你要找的[%s]!" % data[mid]) 19 else: 20 print("不好意思,没有找到你要的值...") 21 22 if __name__ == '__main__': 23 # 创建一个1到6000万的连续数字数组 24 data = list(range(60000000)) 25 # 调用函数找到95938的值 26 search_data(data,95938)
三、列表查找
列表查找:从列表中查找指定元素
输入:列表、待查找元素
输出:元素下标或未查找到元素
一般是有两种方法:
1、顺序查找
从列表第一个元素开始,顺序进行搜索,直到找到为止。
1 def linear_search(data_set,value): 2 for i in data_set: 3 if data_set[i] == value: 4 return i
2、二分查找
从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。
1 def bin_search(data_set,value): 2 low = 0 3 high = len(data_set)-1 4 while low <= high: 5 mid = (low+high)//2 6 if data_set[mid] == value: 7 return mid 8 elif data_set[mid] > value: 9 high = mid - 1 10 else: 11 low = mid + 1
1 def bin_search(data_set,value,low,high): 2 if low <= high: 3 mid = (low+high)//2 4 if data_set[mid] == value: 5 return mid 6 elif data_set[mid] >value: 7 return bin_search(data_set,value,low,high) 8 else: 9 return bin_search(data_set, value, low, high) 10 else: 11 return
练习题:
1 现有一个学员信息列表(按id增序排列),格式为: 2 [ 3 {"id":1001, "name":"张三", "age":20}, 4 {"id":1002, "name":"李四", "age":25}, 5 {"id":1004, "name":"王五", "age":23}, 6 {"id":1007, "name":"赵六", "age":33} 7 ] 8 9 修改二分查找代码,输入学生id,输出该学生在列表中的下标,并输出完整学生信息。
1 l = [ 2 {"id":1001, "name":"张三", "age":20}, 3 {"id":1002, "name":"李四", "age":25}, 4 {"id":1004, "name":"王五", "age":23}, 5 {"id":1007, "name":"赵六", "age":33} 6 ] 7 8 def bin_search(data_set,value): 9 """ 10 二分查找 11 :param data_set: 列表 12 :param value: 要查的值 13 :return: 14 """ 15 low = 0 16 high = len(data_set)-1 17 while low <= high: 18 mid = (low+high)//2 19 if data_set[mid]['id'] == value: 20 return (mid,data_set[mid]) 21 elif data_set[mid]['id'] > value: 22 high = mid - 1 23 else: 24 low = mid + 1 25 else: 26 return (0,None) 27 28 flog = True 29 while flog: 30 sid = input("请输入学号(退出:Q):").strip() 31 if sid.isdigit(): 32 if sid.upper() == "Q": 33 flog = False 34 else: 35 sid = int(sid) 36 mid,infos = bin_search(l,sid) 37 if not infos: 38 print("查无此人!!!") 39 else: 40 s = "学生学号:{id},姓名:{name},年龄:{age}".format(**infos) 41 print("该学生所在信息索引坐标:%s"%mid) 42 print("该学生的所有信息:%s"%s)

浙公网安备 33010602011771号