🔍二分查找(Binary Search)

2026-08-02
⭐⭐ GESP 3级

📖概念讲解

二分查找是一种在有序数组中高效查找目标值的算法。核心思想是:每次把搜索范围缩小一半,而不是一个一个地检查。

💡 生活例子:想象你在翻一本按字母排列的电话簿,想找 "Wang" 的号码。你不会从 A 开始翻,而是直接翻到中间。如果中间是 M 开头的,你知道 Wang 在后半部分,就把前半部分丢掉。然后再对后半部分取中间……每次排除一半,很快就能找到!

算法步骤:

时间复杂度:O(log n) — 即使有一百万个数,最多也只需要约 20 次比较!对比线性查找的 O(n) 快得多。

💻代码示例

1#include <iostream>
2using namespace std;
3
4// 二分查找函数:返回目标值的下标,找不到返回 -1
5int binarySearch(int arr[], int n, int target) {
6 int left = 0, right = n - 1; // 初始化左右边界
7
8 while (left <= right) { // 当搜索范围不为空
9 int mid = left + (right - left) / 2; // 取中间位置(防溢出写法)
10
11 if (arr[mid] == target) {
12 return mid; // 找到目标,返回下标
13 } else if (arr[mid] < target) {
14 left = mid + 1; // 目标在右半部分
15 } else {
16 right = mid - 1; // 目标在左半部分
17 }
18 }
19
20 return -1; // 没找到
21}
22
23int main() {
24 int arr[] = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
25 int n = 10;
26 int target = 23;
27
28 int result = binarySearch(arr, n, target);
29
30 if (result != -1) {
31 cout << "找到了!下标为 " << result << endl;
32 } else {
33 cout << "没有找到" << endl;
34 }
35
36 return 0;
37}

📝 关键行解释:

🧩互动小测

第 1 题:在一个有 1024 个元素的有序数组中,二分查找最多需要几次比较?

第 2 题:二分查找的前提条件是什么?

第 3 题:下面哪种写法可以防止 left + right 整数溢出?

📝易错点提醒

⚠️ 易错点 1:循环条件写错
必须是 while (left <= right),写成 left < right 会漏掉当 left == right 时的最后一次查找。
⚠️ 易错点 2:边界更新漏了 ±1
左边界更新用 left = mid + 1,右边界用 right = mid - 1。如果写成 left = mid 或 right = mid,当只剩两个元素时会死循环!
⚠️ 易错点 3:没排序就用二分
二分查找要求数组必须是有序的!使用前先排序,或者确认输入是排好序的。
⚠️ 易错点 4:mid 计算溢出
(left + right) / 2 在 left 和 right 都很大时可能超出 int 范围。用 left + (right - left) / 2 或 left + (right - left) >> 1 更安全。

🏋️动手练一练

📝 编程练习

给定一个升序排列的整数数组 nums 和一个目标值 target。
请用二分查找找到 target 的下标;如果不存在,返回 -1。

要求:写出完整的 C++ 代码,包含 binarySearch 函数和 main 函数。
提示:注意边界处理和防溢出写法。
参考答案:
#include <iostream>
using namespace std;

int binarySearch(int nums[], int n, int target) {
    int left = 0, right = n - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        else if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

int main() {
    int nums[] = {1, 3, 5, 7, 9, 11};
    int n = 6, target = 7;
    cout << binarySearch(nums, n, target) << endl;  // 输出: 3
    return 0;
}

要点:循环条件 left <= right 不能漏等号;mid 用防溢出写法;更新边界时 +1 / -1 不能省。
🏠 返回主页
学完这个知识点后点一下