您的位置:首页 > 其它

重新认识二分查找算法

2016-01-04 13:36 281 查看
自己也曾写过二分查找算法,可是认识却有点模糊,或者说对算法的流程理解的并不是很透彻。《编程珠玑》里提到用循环不变式的三个性质来检验算法的正确性,即:

1.初始化:保证循环开始前初始条件是正确的。

2.保持:如果在循环的某一次迭代开始之前它是正确的,那么,在下一次迭代开始之前,它也应该保持正确。

3.终止:循环能够终止,并且可以得到期望的结果。

int BinSearch(int *array, int size, int key)  //前置条件是数组已是升序排列
{
if(!array)
return -1;
int left = 0, right = size, mid;
while(left <= right)
{
mid = left + (right - left)/2;    //或右移一位,这种写法是为了防止溢出
if(array[mid] < key)
left = mid + 1;
else if(array[mid] > key)
right = mid - 1;
else
return mid;
}
return -1;
}

如果key在数组中可能重复,要求返回key出现的第一个下标

int BinSearchFirst(int *array, int size, int key)  //前置条件是数组已是升序排列
{
if(!array)
return -1;
int left = 0, right = size, mid;
while(left < right)
{
mid = left + (right - left)/2;    //或右移一位,这种写法是为了防止溢出
if(array[mid] >= key)
right = mid;     //循环减少right-mid,如果right==mid(此时构成死循环),有right==left,因此循环终止条件不包括==
else
left = mid + 1;  //循环减少mid+1-left,至少减少为1
}
if(array[left] == key)   //终止时有left>=right,若left>right,则left上一步有left=mid+1,mid+1>right,退出mid==right,left==right,循环一开始就不会出现
return left;         //若left==right,如果array[left]==key,返回left即可
return -1;
}

对于要求返回最后一个等于key的位置x的算法,情况下更复杂一些.当array[mid]==key时,x可能存在于(mid,…,right)中,此时令left=mid,循环减少mid-left。由于mid通过除法运算舍去小数部分后更靠近left,所以mid==left时有left+1==right或left==right,不同于求第一次出现位置时的right==mid只有一种情况,与上例的主要区别也就在这里。因此循环终止条件应设为left<right-1.

int BinSearchLast(int *array, int size, int key)
{
if(!array)
return -1;
int left = 0, right = size, mid;
while(left < right-1)
{
mid = left + (right - left)/2;
if(array[mid] <= key)
left = mid;
else
right = mid - 1;
}
if(array[right] == key)
return right;
else if(array[left] == key)
return left;
else
return -1;
}

递归版本的二分搜索原理与迭代版本相同,需要注意递归的不变式为判断语句,迭代为循环。

//递归版本的二分搜索
int Search(int *array, int left, int right, int key)
{
int mid = left + (right-left)/2;
if(left <= right)
{
if(array[mid] < key)
return Search(array, mid+1, right, key);
else if(array[mid] > key)
return Search(array, left, mid-1, key);
else
return mid;
}
else
return -1;
}
int BinSearch(int *array, int size, int key)
{
if(!array)
return -1;
int left = 0, right = size;
return Search(array, left, right, key);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: