二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,二分查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
顺序查找、简单查找
介绍二分查找之前,我们先看一下最容易理解的顺序查找或者说简单查找 。
顺序查找也就是傻找,一个一个对比,直到成功匹配查找值。最坏的情况在最后一个元素才匹配到查找值。
- 顺序查找的运行时间是O(n)。
- 顺序查找虽然‘傻’,但是它对数据存储顺序没有要求,是最通用的查找算法。
Python实现如下
生成无序列表
def ord_list(n): #生成有序列表
ord = list(range(n))
return ord
def ran_list(n): #生成无序列表
ran = ord_list(n)
random.shuffle(ran)
return ran
简单查找算法
def simple_search(key,list): #实现简单查找
num=0 #记录操作次数
for index,i in enumerate(list):
num+=1
if key==i:
print('元素{}在列表中的索引为{}'.format(key,index))
print('共查找{}次'.format(num))
return index
输出结果
if __name__=='__main__':
n=10000
key=random.randint(0,n-1) #生成查找值
ran = ran_list(n) #生成无序列表,10000个参数
print('从列表中查找元素{}'.format(key))
simple_search(key,ran)
'''
输出结果如下:
从列表中查找元素1288
[7167, 4864, 4521, 6352, 2578, 6109, 7097,
3186, 2952, 7662, 2372, 8252, 3776, 8912,
......
8038, 5548, 2742, 216, 8100, 104, 691, 7095,
5141, 7030, 9587, 644, 9676, 8165, 481]
元素1288在列表中的索引为7315
共查找7316次
'''
二分查找
当序列为有序时,再使用简单查找那就真的‘傻’了。
二分查找
- 首先要满足顺序序列的前提,以升序为例
- 查找值与序列中间值进行比对
- 如匹配成功则返回中间值索引
- 当查找值大于中间值舍弃前面一半序列,反之舍弃后面一半序列
- 循环进行直到匹配成功,或仅有一个元素仍不满足匹配,则序列中无查找元素
最多需要log n步。
- 二分查找的运行时间时O(log n)
- 二分查找的前提,序列必须是有序
Python实现如下
二分查找算法
def binary_search(key,list):
num = 0 # 查找次数
low = 0 # 最小数下标
high = len(list) - 1 # 最大数下标
while low <= high:
num+=1
mid = (low + high) //2 # 中间数下标
if list[mid] == key: # 如果中间数下标等于key, 返回
print('元素{}在列表中的索引为{}'.format(key, mid))
print('共查找{}次'.format(num))
return mid
elif list[mid] > key: # 如果key在中间数左边, 移动high下标
high = mid - 1
else: # 如果val在中间数右边, 移动low下标
low = mid + 1
print('该列表中不存在元素{}'.format(key))
return # key不存在, 返回None
输出结果
if __name__=='__main__':
n=10000
key=random.randint(0,n-1)
ord = ord_list(n)
print('从列表中查找元素{}'.format(key))
print(ord)
binary_search(key,ord)
'''
输出结果如下:
从列表中查找元素2560
[0, 1, 2, 3, 4, 5,
......
9996, 9997, 9998, 9999]
元素2560在列表中的索引为2560
共查找13次
'''
从10000个元素中查找一个随机数,仅仅需要13步,效率还是相当可观的。
总结
- 二分查找比简单查找快得多
- 二分朝朝要求必须是有序序列
- 简单查找对序列几乎没有要求
- O(log n)比O(n)快。需要搜索的元素越多,前者比后者就快的越多