折半查找法(二分查找)
定义与基本思想
折半查找法(Binary Search)是一种高效的查找方法,适用于有序表。其基本思想是:每次将查找范围折半,逐步缩小查找区间,直到找到目标元素或区间为空。
折半查找法(Binary Search)演示
1357911
适用场景
- 适用于有序的线性表(顺序存储或链式存储)
- 数据量较大、查找频繁的场合
算法描述
- 设查找区间为
- 计算中间位置
- 若 ,查找成功
- 若 ,则在右半区间查找
- 若 ,则在左半区间查找
- 直到 ,查找失败
伪代码如下:
low = 0, high = n-1
while low <= high:
mid = (low + high) // 2
if A[mid] == x:
return mid
elif A[mid] < x:
low = mid + 1
else:
high = mid - 1
return -1
代码实现
// 折半查找(递归实现,要求 A[0..n-1] 递增有序)
int BinarySearch(int A[], int low, int high, int key) {
if (low > high) return -1; // 查找失败
int mid = (low + high) / 2;
if (A[mid] == key) return mid; // 查找成功
else if (A[mid] < key)
return BinarySearch(A, mid + 1, high); // 右半区间
else
return BinarySearch(A, low, mid - 1); // 左半区间
}
判定树与平均查找长度推导
折半查找的过程可以用一棵判定树描述:每个结点代表一次比较的中间位置 mid。
- 判定树是一棵平衡二叉树(或接近平衡),结点数等于表长 n
- 查找成功的最长比较次数 = 判定树的高度
- 平均查找长度约为
以 为例,判定树高度为 ,各层结点数分别为 1、2、4、4,则:
即查找成功平均需要比较 3 次。
时间复杂度分析
- 最好情况:
- 最坏/平均情况:
- 空间复杂度:递归实现 ,迭代实现
二分查找的变体
实际应用中常需要查找边界位置,这类”二分查找变体”是面试高频题:
| 变体 | 查找目标 |
|---|---|
| 第一个等于 key 的位置 | 左边界 |
| 最后一个等于 key 的位置 | 右边界 |
| 第一个大于等于 key 的位置 | 下界(lower_bound) |
| 第一个大于 key 的位置 | 上界(upper_bound) |
实现要点:找到目标后不立即返回,而是继续向一侧收缩区间。
习题
习题 1
给定有序数组 ,用折半查找法查找元素 的位置。
答案与解析
解题思路:每次折半,比较中间元素。
详细步骤:
- ,找到目标
答案: 在数组下标 处。
习题 2
折半查找法的适用条件是什么?其时间复杂度是多少?
答案与解析
解题思路:考查折半查找的前提和效率。
详细步骤:
- 适用于有序表
- 时间复杂度为
答案:适用于有序表,时间复杂度 。
习题 3
折半查找法的查找过程是如何进行的?其查找效率如何?
答案与解析
解题思路:描述查找流程和效率。
详细步骤:
- 每次比较中间元素,缩小一半区间
- 最多比较 次
答案:每次折半,效率 。
