二分法查找
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
递归方式实现
def binary_search(alist,item):
"""
二分查找方式一:递归
:param alist: 列表
:param item: 查找元素(数值)
:return: True 或 False
"""
# 列表的长度n
n = len(alist)
# 如果列表的长度是0的话说明列表中没有找到
if 0 == n:
return False
# 取中间的索引
num = n // 2
# 如果中间的数正好是要找的数返回真
if alist[num] == item:
return True
# 如果中间的数比查找的数大说明要找的数要在前面
elif alist[num] > item:
# 递归查找左边列表
return binary_search(alist[:num],item)
else:
# 递归查找右边列表
return binary_search(alist[num+1:],item)
li = [3,4,7,12,46,73,89,827]
print(binary_search(li,68))
print(binary_search(li,89))
非递归方式实现
def binary_search2(alist,item):
"""
二分查找方式二:非递归
:param alist: 列表
:param item: 查找元素(数值)
:return: True 或 False
"""
# 末尾索引值
end = len(alist) - 1
# 初始索引
start = 0
# 循环查找 当初始位置大于末尾位置说明已经查完退出循环
while start <= end:
# 找中间索引
dim = (start + end) // 2
# 找到返回True
if alist[dim] == item:
return True
# 如果中间数比查找数小说明要在后面部位找
elif alist[dim] < item:
# 后面部位的初始索引
start = dim + 1
else:
# 前面部位的末尾索引
end = dim - 1
# 循环结束说明没找到
return False
li = [3,4,7,12,46,73,89,827]
print(binary_search2(li,68))
print(binary_search2(li,89))
时间复杂度
最优时间复杂度:O(1)
最坏时间复杂度:O(logn)