二分查找(详细)
二分查找
先看一个二分查找的框架吧
{
int left = 0;
int right = ...;
int target = ...;
while(...){
int mid = left + (right - left)/2;
printf("(left = %d,right = %d,mid = %d)\n",left,right,mid);
if(num[mid] == target)
{
...;
}else if(num[mid] < target)
{
left = ...;
}else if(num[mid] > target)
{
right = ...;
}
}
return...
}
接下来以一个例子来理解二分查找
#include<stdio.h>
#include<string.h>
int main()
{
int num[5] = {0,2,3,8,6};
int left = 0;
int length = sizeof(num)/sizeof(int);
int right = length;
int target = 6;
while(left <= right){
int mid = left + (right - left)/2;
// printf("(left = %d,right = %d,mid = %d)\n",left,right,mid);
if(num[mid] == target)
{
printf("\naddress = %d", mid);
return 0;
}else if(num[mid] < target)
{
left = mid + 1;
}else if(num[mid] > target)
{
right = mid - 1;
}
}
printf("\n没找到");
return 0;
}
这个例子表示在数组找一个数,如果找到了就输出它的索引,如果没有找到,那么就显示没找到(也可以用别的方法,这里是为了展示二分法,所以就用二分查找来找)
-
while的括号中是 <=, 因为right = length,即为数组最后一个数的索引,为什么不用<,这两者就相当于区间,前者是[ left , right ],后者就相当于[ left , right),这个算法用闭区间,防止出现越界的情况。
-
在什么时候会“扫描”停止呢?
if(num[mid] == target) { printf("\n address = %d", mid); return 0; }
这段代码代表已经“扫描”到了目标的数,就把找到的数的索引输出
-
没有“扫描”到时就需要while来控制,while循环什么时候停止呢?当“扫描”的区间没有了的时候即会停止,left <= right的停止条件是left ==right + 1,也就相当于[ right+1 , right ],此时“扫描”区间为空,就会跳出循环,且会得到正确结果,如果left < right ,停止条件就是left == right ,也就相当于[ right , right ],我们来待入一个数left = 3,那么这个区间为[ 3, 3 ],我们会发现此时的“扫描”区间不是空,还有一个3,也就是说已经跳出了while 循环,但是我们漏下了索引为3的数,此时就会出现错误,如果你很想用left < right, 那么最后不要忘记判断num[left] == target。
-
对于left = mid + 1,right = mid - 1
本算法的“扫描”区间是两端都闭的,即 [left, right]。那么当我们发现索引 mid 不是要找的 target 时,就去扫描 [left, mid - 1] 或者 [mid + 1, right] , mid 已经搜索过,应该从搜索区间中去除。
上一篇: PHP中session的基础应用一
下一篇: [CQOI2015]任务查询系统