【题目要求】在给定的有序数组中,查找一个给定的val的值,返回它的位置。
【循环实现】:
int BinaryFind(int *arr, int n, int val)
{
int pos = -1;
if (arr == NULL || n < 1)
return pos;
int left = 0, right = n - 1;
while (left <= right)
{
//int mid = (left + right) / 2;//可能超过最大整数。2147483647
int mid = (right - left + 1) / 2 + left;
if (arr[mid] > val)
{
right = mid - 1;
}
else if (arr[mid] < val)
{
left = mid + 1;
}
else
{
pos = mid;
/*
//找最左边
while (arr[pos - 1] == val && pos >= 0)
pos--;
//找最右边
while (arr[pos + 1] == val && pos != n)
pos++;
*/
break;
}
}
return pos;
}
【部分代码解读】:
1,//int mid = (left + right) / 2;//可能超过最大整数。2147483647
int mid = (right - left + 1) / 2 + left;
相信一般第一次想到求中间位置,人们惯性的就想到了 int mid = (left + right )/2这种求法。
但是当数组的个数很大的时候就会出现问题,,,比如我们这里采用的整型数组,那么
当数据个数为21亿的时候,比如要查找的数据在数组靠近末尾的位置,那么我们在某次left + right 就有可能大于int的最大值而,或越界为负数,或越界为正数。那么结果可想而知就出错了。
我们采用int mid = (right - left + 1)/2 + left 可以在一定程度上避免这中情况的发生。增强了程序的健壮性。
2,
/*
//找最左边
while (arr[pos - 1] == val && pos >= 0)
pos--;
//找最右边
while (arr[pos + 1] == val && pos != n)
pos++;
*/
当有多个重复的值的时候可以打开注释代码,选择获取val的最左边,或者最右边的位置。
【代码,返回找到位置的地址】
//用指针来实现返回地址
int *FindValue(int *left, int *right, int val)
{
if (left == NULL || right == NULL)
{
return NULL;
}
int *middle = NULL;
while (left <= right)
{
middle = left + (right - left + 1) / 2;
if (*middle < val)
{
left = middle + 1;
}
else if (*middle > val)
{
right = middle - 1;
}
else return middle;
}
return NULL;
}
【用递归来实现】
int Search(int *arr, int left, int right, int val)
{
int mid = (right - left + 1) / 2 + left;//防止超过int最大值,用这种方法比较号。。。。
if (left > right)
{
return -1;
}
if (arr[mid] < val)
return Search(arr, mid + 1, right, val);
else if (arr[mid] > val)
return Search(arr, left, mid - 1, val);
else
{
while (arr[mid - 1] == val && mid >= 0)
mid--;
return mid;
}
}
【解读】:
while (arr[mid - 1] == val && mid >= 0)
mid--;
这段的目的是为了返回最左边的val的位置。