二分查找(渣新入门)
二分的写法参考了(http://blog.csdn.net/int64ago/article/details/7425727)
下面部分粘贴该博主的博客:
我总结的二分无非就4种情况:YES_LEFT、YES_RIGHT、NO_LEFT、NO_RIGHT,分别代表:能找到且返回最左边的数的位置(如查找4的时候返回位置3)、能找到且返回最右边的数的位置(如查找4的时候返回位置4)、不能找到且返回左边与其接近的数的位置(如查找3的时候返回位置2)、不能找到且返回右边与其接近的数的位置(如查找3的时候返回位置3)。下面是我总结调试的代码:
对于YES_LEFT或者NO_RIGHT
int binaryselect_YLNR(int low, int high, int key)
{
while (low <= high)
{
int mid = (low+high) / 2;
if(a[mid] >= key)
high = mid - 1;
else low = mid + 1;
}
return low;
}
对于YES_RIGHT或者NO_LEFT
int binaryselect_YRNL (int low, int high, int key)
{
while(low <= high)
{
int mid = (low+high) / 2;
if( a[mid] <= key)
low = mid + 1;
else high = mid - 1;
}
return high;
}
以上是我根据转载的博客的写法自己手打了一遍,对于mid值可以写成 low+(high-low)/2 防爆Int;
我自己对这个写法的理解是:
对于YRNL 或者是 YLNR,(即数组中有重复出现元素), 搜到key值后要寻找边界值,即左边界或右边界,倒数第二步时会越过正确值(+1或者-1),之后else(-1或+1),得到正确值。
对于只有一个元素的查找很容易理解这里就不说了。
下面是测试数据:
输入m, n (m是整数个数,n是查询个数)
m个整数:1, 2,3,3,3,5,6
对于YLNR: 查询1,2,3,4,6(边界值,重复值,不存在值)
输出1,2,3,6,7
对于YRNL: 查询1,2,3,4,6
输出1,2,5,5,7
just的就不写了。。。
以上代码均测试通过。
下面贴代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
int a[100];
using namespace std;
int binaryselect_just(int low, int high, int key)
{
while(low <= high)
{
int mid = (low+high) / 2;
if(a[mid]==key) return mid;
else if (a[mid] < key)
low = mid + 1;
else high = mid - 1;
}
}
int binaryselect_YRNL (int low, int high, int key)
{
while(low <= high)
{
int mid = (low+high) / 2;
if( a[mid] <= key)
low = mid + 1;
else high = mid - 1;
}
return high;
}
int binaryselect_YLNR(int low, int high, int key)
{
while (low <= high)
{
int mid = (low+high) / 2;
if(a[mid] >= key)
high = mid - 1;
else low = mid + 1;
}
return low;
}
int main()
{
int n,m;
int key;
while (scanf("%d%d",&n, &m)!=EOF)
{
memset(a, 0, sizeof(a));
for(int i=0; i<n; i++) scanf("%d",&a[i]);
sort(a, a+n);
while(m--)
{
scanf("%d",&key);
printf("%d\n",binaryselect_YRNL(0, n-1, key)+1);
//printf("%d\n",binaryselect_YLNR(0, n-1, key)+1);
//printf("%d\n",binaryselect_just(0, n-1, key)+1);
}
}
return 0;
}
如有错误或建议,希望能提出