目录
什么是二分查找
二分查找是计算机编程中的一种查找算法,在一段有序序列中,通过不断将猜测值与目标值进行比对,逐渐缩小搜索区间,逼近目标值,最后获得目标值位置。如同其名,每次的猜测值为区间内排序中间的值。
例如一个1~10数组 [1,2,3,4,5,6,7,8,9,10],查找9的位置,算法执行过程如下:
开始查找:
区间1倒10,最小值:1,最大值:10,猜测值:(1+10)/2 = 5.5 向下取整为 5
猜测值与目标值对比:5<9 结果:小
重新选择区间,最小值:5,最大值:10,猜测值:(5+10)/2 = 7.5 向下取整为 7
猜测值与目标值比较:7<9 结果:小
重新选择区间,最小值:7,最大值:10,猜测值:(7+10)/2 = 8.5 向下取整为 8
猜测值与目标值比较:8<9 结果:小
重新选择区间,最小值:8,最大值:10,猜测值:(8+10)/2 = 9
猜测值与目标值比较:9=9 结果:相等
结果:9在第九个位置。
小结
观察上面的查找过程:使用二分查找9的位置,一个猜测了四次,如果从左到右查,需要9次,从右到左查,需要2次,从这里不难看出,二分查找是速度非常稳定的查找方法,通过每次缩减二分之一的区间,实现快速逼近。如果是2^10=1024长度的序列,使用普通查找最慢需要1024次,二分查找最慢需要10次,即二分查找的速度为log2n,n是序列长度,log2n表示2的几次幂等于n。
就自然序列而言,读者可能觉得直接看数值就能找到位置,例如上面的位置,但是在一些其他环境中,如用户列表查询,这个列表以[a-z]的顺序排序,而且其中可能涉及删除操作,单列表是有序的单不均匀的,如查找 'Make' ,需要先找到M开头的用户,M****,然后查找Ma**到Mz**,等等,这不是可以直接观察出位置的,二分查找的唯一要求就是有序可循,所以我们也要养成有序储存的习惯。
编程实现
上述例子进行了多次修改区间与对比,可以用循环实现
import math
find = 9999
list = [x for x in range(0,10000)]
def binary_search(find,list):
left = list[0]
right = list[len(list)-1]
giss = (left + right)/2
while left < right:
if giss == find:
print(giss)
return
elif giss > find:
right = giss
giss = math.floor((left + right) / 2)
else:
left = giss
giss = math.ceil((left + right) / 2)
print('none')
binary_search(find,list)
*循环条件为 left<right 意思是只要区间还有一个数字,就可以进行比较查找
*elif和else判断分别使用了向下取整和向上取整,其一是因为python没有明确的指定数的精度,需要转换为int,其二是因为会出现死循环,如我将两个条件的取整方向换一下,elif 向上 else向下,那么当我查找最小值时如下,left = 0 right = 1,
(left + right)/2 = 0.5 向上取整是1,最后right = 1,陷入了死循环。同理,查询最大值也是如此。