欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二分查找(详细)

程序员文章站 2024-03-20 12:43:10
...

二分查找

先看一个二分查找的框架吧

{
	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;
}

这个例子表示在数组找一个数,如果找到了就输出它的索引,如果没有找到,那么就显示没找到(也可以用别的方法,这里是为了展示二分法,所以就用二分查找来找)

  1. while的括号中是 <=, 因为right = length,即为数组最后一个数的索引,为什么不用<,这两者就相当于区间,前者是[ left , right ],后者就相当于[ left , right),这个算法用闭区间,防止出现越界的情况。

  2. 在什么时候会“扫描”停止呢?

    		if(num[mid] == target)
    		{
    			printf("\n address = %d", mid);
    			return 0;
    		}
    

    这段代码代表已经“扫描”到了目标的数,就把找到的数的索引输出

  3. 没有“扫描”到时就需要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。

  4. 对于left = mid + 1,right = mid - 1
    本算法的“扫描”区间是两端都闭的,即 [left, right]。那么当我们发现索引 mid 不是要找的 target 时,就去扫描 [left, mid - 1] 或者 [mid + 1, right] , mid 已经搜索过,应该从搜索区间中去除。