嗨,下面是我的二进制搜索实现的伪代码:
Input: (A[0...n-1], K)
begin
l ← 0; r ← n-1
while l ≤ r do
m ← floor((l+r)/2)
if K > A[m] then l ← m+1
else if K < A[m] then r ← m-1 else return m
end if
end while
return -1 // key not found
end
我只是想知道如何计算这个实现在最坏情况下对于大小为n的排序数组所做的比较次数?
比较次数是否= lg n 1?还是别的什么?
3 回答
在这种情况下最坏的情况是,如果元素K不存在于A中并且小于A中的所有元素 . 那么我们在每个步骤中进行两次比较:
K > A[m]
和K < A[m]
.因为在每个步骤中,数组被切割成两个部分,每个部分的大小为
(n-1)/2
,我们最多有log_2(n-1)
个步骤 .这导致总共
2*log_2(n-1)
比较,其渐近确实等于O(log(n))
.对hielsnoppe's answer的一个非常小的修正:
在
n
-element数组(n > 0
)中,要比较的元素位于索引m = floor((n-1)/2)
. 所以有三种可能性A[m] < K
,然后在一次比较之后,搜索在n-1-m = ceiling((n-1)/2)
-element数组中继续 .A[m] > K
,然后在两次比较后,搜索在m
-element数组中继续 .A[m] == K
,然后我们在两次比较后完成了 .因此,如果我们用
C(n)
表示n
-element数组中搜索的最大(最坏情况)比较次数,我们有对于奇数
n = 2k+1
,地板和天花板是相同的,所以最大值显然是后者,我们发现,甚至
n = 2k
对于
n = 2
,解析为C(2) = 1 + C(1) = 1 + 2 = 3
,对于所有较大的偶数n
,最大值为2 + C(k-1)
,因为对于n >= 1
,我们有C(n) <= C(n+1) <= C(n) + 1
.我们发现,评估前几个
n
的递归所以通过归纳我们证明了
要么
这是一个确切的上限 .
根据binary search上的维基百科页面,该算法的最坏情况性能是
O(lg n)
,它测量所需的渐近数量的比较 . 实际最坏情况下的比较数将是2*lg(n-1)
,正如@ hielsnoppe的回答所指出的那样 .问题中的伪代码表示二进制搜索的典型实现,因此预期的性能复杂性适用于大小为
n
的数组(或向量):最佳案例表现:
O(1)
平均案例表现:
O(lg n)
最差案例表现:
O(lg n)
仔细观察,问题中的伪代码存在两个问题:
行:
if K > A[m] then return l ← m+1
应为if K > A[m] then l ← m+1
. 你还不能回来当使用固定大小的整数时,如果数字足够大,则行:
m ← floor((l+r)/2)
可能会导致溢出 . 正确的语法取决于您正在使用的实际编程语言,但是这样可以解决问题:m ← (l + r) >>> 1
,其中>>>
是无符号右移运算符 . 在here中阅读有关该问题的更多信息 .