进行二分搜索的数组要求是有序的,二分搜索通过持续跟踪数组中包含元素t的范围来解决问题。一开始,这个范围是整个数组,然后通过将t与数组的中间项进行比较并抛弃一半的范围来缩小范围。该过程持续进行,直到在数组中找到t或确定包含t的范围为空时为止,在有n个元素的表中,二分搜索大约需要执行log
2n次比较操作。
1. 最基础的二分查找
下面的的例子为升序情况的二分查找的情况。
示例:如有已排序数组有8个元素如下查找元素x = 5;
1 5 6 7 9 10 12 44
将数组分为两个子段(0+7)/2 = 3:
1 5 6
7
9
10 12 44
比较array[3] = 7与x = 5的大小由于数组为升序:
(1)
若分段点元素大于x,则不用查找分段点以后的元素;
(2)
若分段点元素小于x,则不用查找分段前之前的元素;
(3)
若分段点元素等于x表示已找到该元素,返回。
array[3]比x大,则查找array[4]之前的元素,将array[4]之前的看作一个子数组继续进行二分操作。
语法:
result=search_bin(
int
*t,
int
k
,
int
n
);
| |
参数:
| |
t[]:
|
待查找数组
|
k:
|
查找关键字
|
n:
|
数组元素个数
|
返回值:
|
如果k在t[]中存在,输出i:t[i]=k,否则输出-1
|
注意:
|
数组元素从
0开始存储
|
|
要求查找数组是有序升序序列
|
源程序:
|
|
|
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
2.改进二分查找--若查找的元素出现多次查找第一次出现的位置
我们可以从第一次得代码中知道,上述代码不能确定查找到得元素的位置为第一次出现的位置。
怎么确定查找的元素在该序列中出现的是第一次呢,我们举一个例:
数组:1 2 3 3 3 3 3 5 ;8个元素,查找值为3的元素。
将数组分为两个子段(0+7)/2 = 3:
1 2 3
3
3 3 3 5
此时已查找到3,一种简单的实现方法可以在从该位置开始向前搜索,找到直到不等于3的时候就停止,这个时候找到3的位置就是第一次出现的位置,同理我们也可以用这种方法找到最后出现的3的位置。
语法:
result=search_bin(
int
*t,
int
k
,
int
n
);
| |
参数:
| |
t[]:
|
待查找数组
|
k:
|
查找关键字
|
n:
|
数组元素个数
|
返回值:
|
如果k在t[]中存在,输出i
,i为k在t[]中第一次出现的位置
:t[i]=k,否则输出-1
|
注意:
|
数组元素从
0开始存储
|
|
要求查找数组是有序升序序列
|
源程序:
|
|
|
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
我们通过上面的代码也许可以知道,这样实现确实很简单,但是这样效率确实降低了,如果有一个极端的例子,即一个数组里面的元素全部相同,且我们要查找的元素就是该数组的元素此时在查找第一个出现位置的时候就比较消耗时间,这里我们可以深入一点,继续利用分治的方法查找它第一次出现的位置。
示例:数组:1 2 3 3 3 3 3 5 ;8个元素,查找值为3的元素。
将数组分为两个子段(0+7)/2 = 3:
1 2 3
3
3 3 3 5
在查找到元素后记录该位置
flag ,由于搜索的是第一次出现的位置,所以 应该搜索左子数组,调整搜索上界为mid-1,即为high=2;
在此范围内继续进行二分查找,实际上就是在查找到元素的时候并不停止搜索,而是继续搜索直到搜索子数组不存在。
语法:
result=search_bin(
int
*t,
int
k
,
int
n
);
| |
参数:
| |
t[]:
|
待查找数组
|
k:
|
查找关键字
|
n:
|
数组元素个数
|
返回值:
|
如果k在t[]中存在,输出i
,i为k在t[]中第一次出现的位置
:t[i]=k,否则输出-1
|
注意:
|
数组元素从
0开始存储
|
|
要求查找数组是有序升序序列
|
源程序:
|
|
|
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
另外一种实现该改进的方法是按照《编程珠玑》第9.3节中所讲的进行改进,程序如下:



















测试程序:


















































































转载于:https://blog.51cto.com/buptdtt/741412