一、算法原理
二分查找算法又称折半查找算法,每次将待查找的序列一分为二(经实验,一分为二总是比一分为四、一分为八等等快),首先用待查找的目标值target与中间值middle比较,如果待查找值在左侧则直接舍弃右侧,若待查找值在右侧则直接舍弃左侧,若相等则查找结束。
举例说明:比如在待查找序列[18, 19, 22, 24, 56, 60, 66, 77, 88]中查找目标值66。
简单来说,右侧半截为60 66 77 88,而目标值是66,所以直接丢掉左侧序列18 19 22 24,因为56是中间值已经比较过,所以被丢弃。如此反复上面的过程,直到找到66这个值所在位置。
二、实现过程
# 自定义二分查找函数
def search(data, target):
# 待查找序列的左侧边
left = 0
# 待查找序列的右侧边
right = 8
# 循环判断左侧小于等于右侧且键值不等于-1 。输入-1代表结束程序。
while left <= right and target != -1:
# 二分向下取整
mid = (left + right) // 2
# 如果目标值等于边界值
if target == data[mid]:
# 返回边界位置
return mid
# 如果目标值小于边界值
elif target < data[mid]:
# 输出在左半边查找
print(
"%d介于位置%d[%d]和边界值%d[%d]之间,找左半边"
% (target, left + 1, data[left], mid + 1, data[mid])
)
# 最高位等于边界位置减1
right = mid - 1
# 如果目标值大于边界值
elif target > data[mid]:
# 输出在右半边查找
print(
"%d介于边界值位置%d[%d]和%d[%d]之间,找右半边"
% (target, mid + 1, data[mid], right + 1, data[right])
)
# 最低位等于边界位置加1
left = mid + 1
# 自定义函数到此结束
return -1
# 即将查找的目标值
target = 66
# 待查找的数列
data = [18, 19, 22, 24, 56, 60, 66, 77, 88]
i = search(data, target)
print(i)
三、面向对象写法
class serach_alchemist(): # 继承
# 天生
def __init__(self, nums, target, left, right): # 不定长参数
self.n = nums
self.t = target
self.l = left
self.r = right
# self.m = mid
# 二分查找
def search_insert_position(self):
'''
:return:
-1 没找到
-2 无法查找
其他:表示找到的下标
'''
while self.l <= self.r:
self.m = (self.l + self.r) // 2
# 算法
if self.t == self.n[self.m]:
return self.m
elif self.t < self.n[self.m]:
self.r = self.m - 1
elif self.t > self.n[self.m]:
self.l = self.m + 1
else:
return -1
return -2
# 插补查找
def cb(self):
while self.l <= self.r:
self.m = self.l + int((self.t - self.n[self.l]) * (self.r - self.l) / (self.n[self.r] - self.n[self.l]))
# 算法
if self.t < self.n[self.m]:
self.r = self.m - 1
elif self.t > self.n[self.m]:
self.l = self.m + 1
elif self.t == self.n[self.m]:
return self.m
else:
return -1
return -2
# 实例化--->从无到有,从类变成对象 --->实际上就是在执行__init__()
# def __init__(self,nums,target,left,right,mid):
n1 = [1, 3, 5, 6, 7, 8, 10, 12, 15, 20, 21, 22, 24, 33]
t1 = 12
l1 = 0
r1 = len(n1) - 1
sa = serach_alchemist(n1, t1, l1, r1) # 型参
# 目的是调用search_insert_position()
result = sa.search_insert_position() # 二分查找得到的结果
print(result)
n2 = [1, 3, 5, 6, 7, 8, 10, 12, 15, 20, 21, 22, 24, 33]
t2 = 5
l2 = 0
r2 = len(n1) - 1
sa2 = serach_alchemist(n2, t2, l2, r2) # 型参
resultcb = sa2.cb() # 插补查找得到的结果
print(resultcb)