BinarySearch 二分查找法(折半查找法)

问题

在长度为nn的升序(从小到大)序列ss中查找元素xx的位置。

解法

low=0,high=n1,mid=low+high2low = 0, high = n-1, mid = \lfloor \frac{low+high}{2} \rfloor,元素xxmidmid的关系有三种情况:

(1) 若x=s[mid]x = s[mid],显然已经查询到元素xx的位置,算法结束;

(2) 若x<s[mid]x \lt s[mid],则xx处于s[mid]s[mid]左边;

(3) 若x>s[mid]x \gt s[mid],则xx处于s[mid]s[mid]右边;

该操作用伪代码表示为:

function Search(s, low, high, x):
    let mid = (low + high) / 2
    if x = s[mid]
        return true, mid
    else if x < s[mid]
        return false, low, mid-1
    else if x > s[mid]
        return false, mid+1, high

(1) Search函数第2行:计算搜索范围的中间位置midmid,以s[mid]s[mid]为基准与xx进行比较;

(2) Search函数第3-8行:比较s[mid]s[mid]xx,若x=s[mid]x = s[mid]则找到结果,若x<s[mid]x \lt s[mid]则在s[low,mid1]s[low, mid-1]继续寻找,若x>s[mid]x \gt s[mid]则在s[mid+1,high]s[mid+1, high]继续寻找;

上述操作,可以用下图中的示例:

x=17=s[mid]x = 17 = s[mid],可以直接找到x=s[4]x = s[4]

x=5<s[mid]=17x = 5 \lt s[mid] = 17,则令high=3high = 3之后继续搜索:

x=30>s[mid]=17x = 30 \gt s[mid] = 17,则令low=5low = 5之后继续搜索:

外围只需循环调用Search函数即可:

function BinarySearch(s, n, x):
    let low = 0, high = n-1
    while low <= high
        let found, low, high = Search(s, low, high, x)
        if found
            return low
    return -1

复杂度

Search函数的输入规模为T(4)T(4),该函数中最多有1次加法、1次除法、3次比较操作,因此时间复杂度为

T(4)=O(5)=O(1)T(4) = O(5) = O(1)

BinarySearch函数的输入规模为T(n)T(n),每次调用Search函数后highlowhigh - low的值都会减小一半,即

T(n)=T(n2)+O(1)=T(n22)+2O(1)=T(n23)+3O(1)=\begin{matrix} T(n) & = & T(\frac{n}{2}) + O(1) \\ & = & T(\frac{n}{2^2}) + 2 \cdot O(1) \\ & = & T(\frac{n}{2^3}) + 3 \cdot O(1) \\ & = & \cdots \end{matrix}

假设递归层数为LL,可得:

T(n2L)=1T(\frac{n}{2^L}) = 1

即:

L=T(log2n)=O(log2n)L = T(log_2 n) = O(log_2 n)

LL代入原始递推公式,可得:

T(n)=T(n2L)+LO(1)=O(1)+O(log2n)O(1)=O(log2n)\begin{matrix} T(n) & = & T(\frac{n}{2^L}) + L \cdot O(1) \\ & = & O(1) + O(log_2 n) \cdot O(1) \\ & = & O(log_2 n) \end{matrix}

该算法时间复杂度为O(log2n)O(log_2 n),空间复杂度为O(1)O(1)

源码

BinarySearch.h

BinarySearch.cpp

测试

BinarySearchTest.cpp

Last updated