算法概述
二分查找是一种在有序数组中查找特定元素的搜索算法。他的核心思想是通过不断将搜索范围减半来快速定位目标元素,通过先查询到中间元素,再根据目标字的位置决定继续向左还是向右查找。与线性查找(行第一个元素开始逐个比对)相比,二分查找的效率会高很多。
核心思路和原理
二分查找的核心思想是 分而治之。算法的工作原理如下:
- 确定搜索范围: 初始化左边界 left 为 0,右边界 right 为数组长度 -1;
- 计算中间位置:
mid = (left + right) // 2 - 比较中间元素:
- 如果
arr[mid]等于目标值, 返回 mid; - 如果
arr[mid]小于目标值, 说明目标在右半部分, 将 left 设置为 mid+1; - 如果
arr[mid]大于目标值, 说明目标在左半部分, 将 right 设置为 mid-1;
- 如果
- 重复步骤 2-3: 直至找到目标或者搜索范围为空。
关键概念:
- 有序性要求: 二分查找要求数组必须是有序的,这是算法能够工作的前提;
- 边界条件: 循环条件是
left <= right, 当left > right时说明搜索范围为空;- 中间位置计算: 使
(left + right) // 2可以避免整数溢出问题.
算法流程图
流程图说明:
- 算法从检查搜索范围是否有效开始(left <= right)
- 每次循环计算中间位置 mid,比较中间元素与目标值
- 根据比较结果调整搜索范围(左半部分或右半部分)
- 如果找到目标值立即返回,否则继续缩小搜索范围
- 当搜索范围为空时,说明目标不存在,返回 -1
详细示例演示
假设我们要在有序数组 [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] 中查找目标值 23 。
-
第 1 轮查找:
- left = 0, right = 9
- mid = (0 + 9) // 2 = 4
- arr[4] = 16 < 23,说明目标在右半部分
- 调整:left = mid + 1 = 5
-
第 2 轮查找:
- left = 5, right = 9
- mid = (5 + 9) // 2 = 7
- arr[7] = 56 > 23,说明目标在左半部分
- 调整:right = mid - 1 = 6
-
第 3 轮查找:
- left = 5, right = 6
- mid = (5 + 6) // 2 = 5
- arr[5] = 23 == 23,找到目标!
- 返回索引 5
-
查找过程总结:
- 初始范围:0-9,中间元素 16
- 调整后范围:5-9,中间元素 56
- 调整后范围:5-6,中间元素 23(找到)
总共比较 3 次,而线性查找需要 6 次
Python 代码实现
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1 # 未找到目标元素
if __name__ == '__main__':
arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
target = 23
index = binary_search(arr, target)
if index != -1:
print(f"目标元素 {target} 找到,索引为 {index}")
else:
print(f"目标元素 {target} 未找到")
代码说明:
- 使用 while 循环控制搜索过程,条件是 left <= right
- 每次循环计算中间位置 mid,避免使用 (left + right) // 2 可能导致的整数溢出
- 通过比较中间元素与目标值,不断缩小搜索范围
- 如果找到目标立即返回索引,否则循环结束后返回 -1