二分查找算法:必须处理有序的表
l = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66,77,88,99,111,222,333,444,555] # 需求:有500W个数据,找里面的一个值 # 思路一,通过切片来查找 def find(l,aim): mid_index = len(l) //2 # 找到列表中间的索引值 if l[mid_index]<aim: # 如果中间的值小于对比值 new_l = l[mid_index+1:] # 产生一个新的列表,以中间值为起始的列表 find(new_l,aim) # 递归函数 重复调用 elif l[mid_index]>aim: new_l = l[:mid_index] find(new_l,aim) else: # 当找到匹配值的时候就输出下面代码 print('找到了!',mid_index,l[mid_index]) find(l,88)
执行完以上代码后,发现索引位置不对
# 进阶:获取到正确的索引值,不再引用切片 def find(l,aim,start = 0,end = len(l)): # 设定默认值,默认列表开始,和列表结束的位置 mid_index = (end - start)//2 + start # 获取中间的索引值 if l[mid_index] < aim: # 如果中间值小于比较值 find(l,aim,start = mid_index+1,end = end) # 则改变默认参数 列表开始索引的位置 elif l[mid_index] > aim: find(l,aim,start = start,end = mid_index-1) else: print('找到了', mid_index,aim) find(l,88)
执行完以上代码后,索引问题已经解决,但是依旧存在问题:
问题一:默认参数end有问题,正常情况下,函数体是写在最开头的,但刚刚函数体是写在变量(列表)之后,所以end里的len(l)能正常调用,实际情况是应该调用一个未知的列表参数。
问题二:如果查找列表中不存在的值呢?
问题三:没有返回值。
# 解决问题1,思路:将改变默认参数 def find(l,aim,start = 0,end = None): # 修改默认参数end值,就可以引用未知变量了 end = len(l) if end is None else end # 三元运算,获取未知列表的长度,因为用递归函数,所有要做判断,若不判断 end = len(l)永不变,无法取到正确的长度 mid_index = (end - start)//2 + start # 获取中间的索引值 if l[mid_index] < aim: # 如果中间值小于比较值 find(l,aim,start = mid_index+1,end = end) # 则改变默认参数 列表开始索引的位置 elif l[mid_index] > aim: find(l,aim,start = start,end = mid_index-1) else: print('找到了', mid_index,aim) l = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66,77,88,99,111,222,333,444,555] find(l,88)
# 解决问题:如果要找的值不在列表里 def find(l,aim,start = 0,end = None): # 修改默认参数end值,就可以引用未知变量了 end = len(l) if end is None else end # 三元运算,获取未知列表的长度,因为用递归函数,所有要做判断,若不判断 end = len(l)永不变,无法取到正确的长度 if start <= end: # 增加一个开始和结束的条件判断 mid_index = (end - start)//2 + start # 获取中间的索引值 if l[mid_index] < aim: # 如果中间值小于比较值 find(l,aim,start = mid_index+1,end = end) # 则改变默认参数 列表开始索引的位置 elif l[mid_index] > aim: find(l,aim,start = start,end = mid_index-1) else: print('找到了', mid_index,aim) else: print("找不到你要找的值") l = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66,77,88,99,111,222,333,444,555] find(l,50)
# 解决,返回值 def find(l,aim,start = 0,end = None): # 修改默认参数end值,就可以引用未知变量了 end = len(l) if end is None else end # 三元运算,获取未知列表的长度,因为用递归函数,所有要做判断,若不判断 end = len(l)永不变,无法取到正确的长度 if start <= end: # 增加一个开始和结束的条件判断 mid_index = (end - start)//2 + start # 获取中间的索引值 if l[mid_index] < aim: # 如果中间值小于比较值 return find(l,aim,start = mid_index+1,end = end) # 则改变默认参数 列表开始索引的位置 elif l[mid_index] > aim: return find(l,aim,start = start,end = mid_index-1) # 只要调用递归,所有结束语句添加return else: return print('找到了', mid_index,aim) else: return "找不到你要找的值" l = [1,2,3,4,5,6,7,8,9,10,11,22,33,44,55,66,77,88,99,111,222,333,444,555] ret = find(l,50) print(ret)