一下是一个正确的二分查找程序:
int search(int array[], int n, int v)
{
int left, right, middle;
left = 0, right = n - 1;
while (left <= right)
{
middle = (left + right) / 2;
if (array[middle] > v)
{
right = middle;
}
else if (array[middle] < v)
{
left = middle;
}
else
{
return middle;
}
}
return -1;
}
这个程序存在一些问题:
1、 这个查找程序只是找到存在元素的标号,但是元素的位置不定,也就是说如果序列中存在多个所查询的值,返回的并不一定是第一个或者是最后一个的后一个位置。
2、 运用middle=(left+right)/2可能导致溢出,所以更加安全的做法就是middle=left+(right-left)/2
下面提供两个更合适的程序
1、 返回序列中第一个所查元素的标号。
int low_bound(int array[], int n, int v)
{
int left, right, middle;
left = 0, right = n - 1;
while (left != right)
{
middle=left+(right-left)/2;
if (array[middle] < v)
left = middle+1;
else //因为当仅剩余两个元素的时候,middle=left
right = middle; //所以改变right可以跳出循环
}
if(array[left] == v) //此时left(left=right)的标号就是元素应当插入的位置
return left; //如果将这里的判定删除,仅仅是返回left
else //的话那就是指元素应当被插入的位置。
return -1;
}
2、返回最后一个元素位置
int up_bound(int array[], int n, int v)
{
int left, right, middle;
left = 0, right = n - 1;
while (left != right)
{
middle=left+(right-left)/2;
if (array[middle] > v)
right = middle;
else
left = middle+1; //用这种方式返回的是插入位置,所以接下来进行判定
} //!!!!只有这样才可以跳出循环!!!!!
if(array[left-1] == v) //一般要返回元素是否存在的程序,都不用up_bound
return left-1;
else
return -1;
}
测试程序:
int main()
{
int a[10]={1,1,6,6,6,6,7,7,7,9};
//int index=search(a,10,6);
//int index=low_bound(a,10,5);
int index=up_bound(a,10,5);
//int index=binary_search(a,10,6);
printf("%d",index);
return 0;
}