二分查找
1、算法简介
二分查找也称折半查找(
B
i
n
a
r
y
Binary
Binary
S
e
a
r
c
h
Search
Search),它是一种效率较高的查找方法。但是,该算法要求数组必须采用顺序存储结构,而且数组中元素按关键字有序排列。(这里的数组只是一个抽象概念,不一定只存储数值,但是本文的数据结构由于个人水平有限,在实现算法时并未做到较高的普适性)
2、思路分析
首先,假设数组中元素是按非降序排列的,将数组中间位置的元素,与待查找元素进行比较,如果两者相等,则查找成功;
否则利用中间位置记录将数组分成前、后两个子数组,如果中间位置的元素大于查找元素,则进一步查找前子数组,否则进一步查找后子数组。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子数组不存在为止,此时查找不成功。
下面我们先用伪代码实现一下算法思路:
算法输入:非降序(非升序也可)排列的数组
A
[
n
]
A[n]
A[n](含有
n
n
n个元素),数组长度
n
n
n和待查找元素
x
x
x。
算法输出:如果
x
=
A
[
i
]
,
0
⩽
i
<
n
x=A[i],0\leqslant i< n
x=A[i],0⩽i<n,则输出
j
j
j,否则输出
−
1
-1
−1。
伪代码:
l
o
w
←
0
;
h
i
g
h
←
n
−
1
;
i
←
−
1
low\leftarrow0\space;\space high\leftarrow n-1\space;\space i\leftarrow-1
low←0 ; high←n−1 ; i←−1
w
h
i
l
e
(
l
o
w
⩽
h
i
g
h
)
a
n
d
(
i
=
=
−
1
)
while(low\leqslant high)\space and\space(i ==-1)
while(low⩽high) and (i==−1)
m
i
d
←
(
l
o
w
+
h
i
g
h
)
/
2
\hspace{1cm}mid\leftarrow(low+high)/2
mid←(low+high)/2
i
f
(
x
=
=
A
[
m
i
d
]
)
t
h
e
n
i
←
m
i
d
\hspace{1cm}if(x==A[mid])\space\space then\space\space i\leftarrow mid
if(x==A[mid]) then i←mid
e
l
s
e
i
f
(
x
<
A
[
m
i
d
]
)
t
h
e
n
h
i
g
h
←
m
i
d
−
1
\hspace{1cm}else\space if(x<A[mid])\space\space then\space\space high\leftarrow mid-1
else if(x<A[mid]) then high←mid−1
e
l
s
e
l
o
w
←
m
i
d
+
1
\hspace{1cm}else\space\space low\leftarrow mid+1
else low←mid+1
e
n
d
w
h
i
l
e
end\space while
end while
r
e
t
u
r
n
i
return\space i
return i
3、时间复杂度分析
根据思路分析,二分查找的核心相信大家已经清楚了,那么我们主要从输入数组的规模着手进行考虑。
(
1
)
(1)
(1) 当
n
n
n等于
1
1
1时,一次判断就可=可以解决问题,所以
T
(
1
)
=
1
T(1)=1
T(1)=1;
(
2
)
(2)
(2) 当
n
⩾
2
n\geqslant2
n⩾2时,我们需要先进行一次判断,如果找到指定元素,则问题解决;如果没有找到,数组就被分为规格相等的两份(近似均等),并将其中一份剔除,所以
T
(
n
)
=
T
(
⌊
n
2
⌋
)
+
1
T(n)=T(\lfloor\frac{n}{2}\rfloor)+1
T(n)=T(⌊2n⌋)+1;
(
3
)
(3)
(3) 综上,得到时间复杂度表达式
T
(
n
)
=
{
1
i
f
n
=
=
1
T
(
⌊
n
2
⌋
)
+
1
i
f
n
⩾
2
T(n)=\begin{cases}1\hspace{1cm}if\space n==1\\\\T(\lfloor\frac{n}{2}\rfloor)+1\hspace{1cm}if\space n\geqslant2\end{cases}
T(n)=⎩⎪⎨⎪⎧1if n==1T(⌊2n⌋)+1if n⩾2
⇒
T
(
n
)
=
T
(
⌊
n
2
⌋
)
+
1
=
T
(
⌊
n
2
2
⌋
)
+
1
+
1
=
⋯
=
T
(
⌊
n
2
i
⌋
)
+
i
\Rightarrow T(n)=T(\lfloor\frac{n}{2}\rfloor)+1=T(\lfloor\frac{n}{2^2}\rfloor)+1+1=\cdots=T(\lfloor\frac{n}{2^i}\rfloor)+i
⇒T(n)=T(⌊2n⌋)+1=T(⌊22n⌋)+1+1=⋯=T(⌊2in⌋)+i
⇒
T
(
n
)
=
T
(
⌊
n
2
⌊
log
n
⌋
⌋
)
+
⌊
log
n
⌋
=
T
(
1
)
+
⌊
log
n
⌋
=
1
+
⌊
log
n
⌋
=
Θ
(
log
n
)
\Rightarrow T(n)=T(\lfloor\frac{n}{2^{\lfloor\log n\rfloor}}\rfloor)+\lfloor\log n\rfloor=T(1)+\lfloor\log n\rfloor=1+\lfloor\log n\rfloor=\Theta(\log n)
⇒T(n)=T(⌊2⌊logn⌋n⌋)+⌊logn⌋=T(1)+⌊logn⌋=1+⌊logn⌋=Θ(logn)
因此,得到算法时间复杂度的渐进的阶为
log
n
\log n
logn。
4、 C + + C++ C++实现
int binary_search(int *A, int n, int x){
int low = 0, high = n-1, i = -1, mid;
while(low <= high && i == -1){
mid = (low + high) / 2;
if(x == A[mid]) i = mid;
else if(x < A[mid]) high = mid - 1;
else low = mid + 1;
}
return i;
}
5、 P y t h o n Python Python实现
def binary_search(A, n, x):
low = 0
high = n - 1
i = -1
while low <= high and i == -1:
mid = int((low + high) / 2)
if x == A[mid]:
i = mid
elif x < A[mid]:
high = mid - 1
else:
low = mid + 1
return i
6、 J a v a Java Java实现
public static int binarySearch(int[] A, int n, int x) {
int low = 0, high = n - 1, i = -1, mid;
while (low <= high && i == -1) {
mid = (low + high) / 2;
if (x == A[mid]) {
i = mid;
} else if (x < A[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return i;
}