原理
-
二分查找
- 又称折半查找
- 优点是比较次数少,查找速度快,平均性能好;
- 缺点是要求待查表为有序表,且插入删除困难。
- 查找方法适用于不经常变动而查找频繁的有序列表。
- 最优时间复杂度:O(1)
- 最坏时间复杂度:O(logn)
- 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
- 否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
- 重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表为空,此时查找不成功。
1、递归法
def binary_search_recursion(alist, value, low, high):
if high < low:
return None
mid = (low + high) // 2
if alist[mid] > value:
return binary_search_recursion(alist, value, low, mid - 1)
elif alist[mid] < value:
return binary_search_recursion(alist, value, mid + 1, high)
else:
return mid
2、迭代法
def binary_search_loop(alist, value):
low, high = 0, len(alist) - 1
while low <= high:
mid = (low + high) // 2
if alist[mid] < value:
low = mid + 1
elif alist[mid] > value:
high = mid - 1
else:
return mid
return None
3、bisect模块
bisect 模块,用于维护有序列表。
bisect 模块实现了一个算法用于插入元素到有序列表。在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高。
Bisect 是二分法的意思,这里使用二分法来排序,它会将一个元素插入到一个有序列表的合适位置,这使得不需要每次调用 sort 的方式维护有序列表。
def binary_search_bisect(alist, x):
from bisect import bisect_left
i = bisect_left(alist, x)
if i != len(lst) and lst[i] == x:
return i
return None