折半查找法(二分查找)

定义与基本思想

折半查找法(Binary Search)是一种高效的查找方法,适用于有序表。其基本思想是:每次将查找范围折半,逐步缩小查找区间,直到找到目标元素或区间为空。

折半查找法(Binary Search)演示

1357911

适用场景

  • 适用于有序的线性表(顺序存储或链式存储)
  • 数据量较大、查找频繁的场合

算法描述

  1. 设查找区间为 [low,high][low, high]
  2. 计算中间位置 mid=(low+high)/2mid = \lfloor (low + high) / 2 \rfloor
  3. A[mid]=xA[mid] = x,查找成功
  4. A[mid]<xA[mid] < x,则在右半区间查找
  5. A[mid]>xA[mid] > x,则在左半区间查找
  6. 直到 low>highlow > high,查找失败

伪代码如下:

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
  • 查找成功的最长比较次数 = 判定树的高度 =log2(n+1)= \lceil \log_2(n+1) \rceil
  • 平均查找长度约为 ASLlog2(n+1)1ASL \approx \log_2(n+1) - 1

n=11n=11 为例,判定树高度为 log212=4\lceil \log_2 12 \rceil = 4,各层结点数分别为 1、2、4、4,则:

ASL=1×1+2×2+3×4+4×411=1+4+12+1611=3311=3ASL = \frac{1\times1 + 2\times2 + 3\times4 + 4\times4}{11} = \frac{1+4+12+16}{11} = \frac{33}{11} = 3

即查找成功平均需要比较 3 次。

时间复杂度分析

  • 最好情况:O(1)O(1)
  • 最坏/平均情况:O(log2n)O(\log_2 n)
  • 空间复杂度:递归实现 O(logn)O(\log n),迭代实现 O(1)O(1)

二分查找的变体

实际应用中常需要查找边界位置,这类”二分查找变体”是面试高频题:

变体查找目标
第一个等于 key 的位置左边界
最后一个等于 key 的位置右边界
第一个大于等于 key 的位置下界(lower_bound)
第一个大于 key 的位置上界(upper_bound)

实现要点:找到目标后不立即返回,而是继续向一侧收缩区间。

习题

习题 1

给定有序数组 A=[1,3,5,7,9,11]A = [1, 3, 5, 7, 9, 11],用折半查找法查找元素 77 的位置。

答案与解析

解题思路:每次折半,比较中间元素。

详细步骤

  1. low=0,high=5,mid=2,A[2]=5<7low=0, high=5, mid=2, A[2]=5 < 7
  2. low=3,high=5,mid=4,A[4]=9>7low=3, high=5, mid=4, A[4]=9 > 7
  3. low=3,high=3,mid=3,A[3]=7low=3, high=3, mid=3, A[3]=7,找到目标

答案77 在数组下标 33 处。

习题 2

折半查找法的适用条件是什么?其时间复杂度是多少?

答案与解析

解题思路:考查折半查找的前提和效率。

详细步骤

  1. 适用于有序表
  2. 时间复杂度为 O(log2n)O(\log_2 n)

答案:适用于有序表,时间复杂度 O(log2n)O(\log_2 n)

习题 3

折半查找法的查找过程是如何进行的?其查找效率如何?

答案与解析

解题思路:描述查找流程和效率。

详细步骤

  1. 每次比较中间元素,缩小一半区间
  2. 最多比较 log2n\log_2 n

答案:每次折半,效率 O(log2n)O(\log_2 n)