二分查找假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
- 优点:比较次数少,查找速度快,平均性能好;
- 缺点:要求待查表为有序顺序表,且插入删除困难。
- 二分查找方法适用于不经常变动而查找频繁的有序列表。
- 二分查找最优时间复杂度是
O
(
1
)
O(1)
O(1),最坏时间复杂度为
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n)。
假设总共有 n n n个元素,查找操作次数为 k k k,则每次查找的区间大小就是 n , n 2 , n 4 , … , n 2 k n,\frac{n}{2},\frac{n}{4},…,\frac{n}{2^k} n,2n,4n,…,2kn(接下来操作元素的剩余个数)。最好第一次操作就找到元素,时间复杂度为 O ( n ) O(n) O(n),最坏最后剩余的一个元素才是要查找的元素,即 n 2 k = 1 ⟹ k = l o g 2 n \frac{n}{2^k}=1\Longrightarrow k=log_2n 2kn=1⟹k=log2n(假设是整数),时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)
递归实现二分查找
# 返回 x 在 arr 中的索引,如果不存在返回 -1
def binarySearch (arr, l, r, x):
# 基本判断
if l <= r:
mid = (l+r)//2
# 元素整好的中间位置
if arr[mid] == x:
return mid
# 元素小于中间位置的元素,只需要再比较左边的元素
elif arr[mid] > x:
return binarySearch(arr, l, mid-1, x)
# 元素大于中间位置的元素,只需要再比较右边的元素
else:
return binarySearch(arr, mid+1, r, x)
else:
# 不存在
return -1
# 函数调用
result = binarySearch(arr, 0, len(arr)-1, x)
非递归实现二分查找
def binarySearch (arr, x):
n=len(arr)
l,r=0,n-1
while l<=r:
mid=(l+r)//2
if arr[mid]==x:
return mid
elif arr[mid]>x
r=mid-1
else:
l=mid+1
return -1