二分查找的前提:数组本身是有序组织的。
算法思想:采用分治策略,每进一步都将问题规模减半,最多经过logN次(对数的底为2)查找能得到结果。
算法实现:有循环和递归两种方法,递归需要更多的函数嵌套调用,函数执行时栈帧的开销大,当然选择循环的写法。
C语言举例说明:对已排好序的整数数组(arr大小为size,升序排列)进行二分查找,函数声明为:
int *binary_search(int *arr, int size, int x);
x为要查找的值,返回x在数组中出现的位置(从0开始),或者NULL(x未在数组中出现)。
N为问题的规模(数组length),二分查找的时间复杂度为O(logN)
比较常见的一个版本(不对称边界的写法,0 <= index < n):
int *bsearch(int *t, int n, int x)
{
int low = 0, high = n;
while(low < high)
{
int mid = (low + high) >> 1;//按位右移1位相当于除以2
int *p = t + mid;
if(x < *p)
high = mid;
else if(x > *p)
low = mid + 1;
else
return p;
}
return NULL;
}
若采用对称边界的写法(0 <= index <= n-1),则表达如下:
int *bsearch2(int *t, int n, int x)
{
int low = 0, high = n - 1;
while(low <= high)
{
int mid = (low + high) >> 1;
int *p = t + mid;
if(x < *p)
high = mid - 1;
else if(x > *p)
low = mid + 1;
else
return p;
}
return NULL;
}
若习惯于指针操作,可写出如下版本:
int *bsearch_ptr(int *t, int n, int x)
{
int *low = t, *high = t + n;
while(low < high)
{
int *mid = t + ((high-low) >> 1);
if(x < *mid)
high = mid;
else if(x > *mid)
low = mid + 1;
else
return mid;
}
return NULL;
}