去创新工厂做了一下笔试题,发现一个二分查找也竟然写错,真服了。
现在再补上吧。
我把最终的要求简化一下。要求是:在一个升序的序列中,找出满足 第一个 不小于(大于或者等于)待查找元素 在数组中的位置。
如: 如果数组是 2, 4, 6, 8 (数组下标从0开始),要查找3时,此时就要返回4 在数组中的位置了
下面是简单的程序实现
#include <stdio.h>
///////////////////////////////////////////////////////////////////
// 功能描述:二分查找, 数组是按照升序排序的, 返回数组中第一个
// 不小于待查找元素的 的位置
// 如: 2, 4, 6 , 9 如果查找 5 , 则返回2 (下标从0开始)
// 输入参数:
// a:查找数组的指针
// n:指针a指向的数组的元素个数
// search:待查找的元素(要求 search >0 && search <= a[n-1])
// 输出参数:
// 无
//
// 返回值:
// -1:search范围有误
// 返回第一个不小于待查找元素在数组中的位置
//
////////////////////////////////////////////////////////////////////
int mid_search(int *a, int n, int search)
{
if (search<0 || search>a[n-1])
return -1;
int low = 0, high = n-1;
int middle = 0;
while (low<=high){
middle = (low+high)/2;
if (a[middle]==search)
return middle;
if (a[middle]<search)
low = middle + 1;
else
high = middle - 1;
}
return low;
}
//main 测试
int main()
{
int a[10] = {2, 10, 20, 30, 40, 50, 60, 70, 80, 90};
int search_num[5] = {-1, 1, 100, 50, 66};
int i = 0, res = 0;
for (i=0; i<10; i++){
printf("%d",a[i]);
if (i<9)
printf("\t");
}
printf("\n");
for (i=0; i<5; i++){
printf("%d \t", search_num[i]);
res = mid_search(a, 10, search_num[i]);
printf("%d\n", res);
}
return 0;
}
其实,这个地方的着急就在于,当待查找的元素和数组中的元素不相等的时候,那么返回的位置是哪个? low? high? or..
其实当待查找元素在数组中不存在时,最后一次循环 low 和 high 最终会指向同一元素, 此时我们将所有的元素可以分为三部分 a[0]---a[low-1], a[low](a[high]), a[low+1]--a[n-1], (middle,low 和 high 指向同一元素)。
由于循环我们可以知道, search_num (待查找元素) 肯定是大于 a[0]---a[low-1], 肯定小于 a[low+1]--a[n-1], 所以我们要找的结果,要么是目前的low的位置,或者就是low+1的位置(看a[low]和search的大小)。
1) 相等的情况不说了
2) a[low] > search 时,此时目前的low 就是我们需要的位置,看循环的执行,此时是把high的值改变,low的值没变,所以循环结束的low值就是要返回的结果.
3) a[low] < search 时, 应该返回的是 目前的 low+1的位置,那看循环执行是将 low = middle+1(low==middle). 所以循环结束时的low值即为要找的位置。
好了,我们返回low值就可以了。
二分查找算法优化与理解
本文详细解析了二分查找算法的实现细节,并通过代码实例展示了如何在升序序列中找到第一个不小于待查找元素的位置。重点分析了查找过程中元素不相等时的返回逻辑,以及待查找元素不在数组中时的返回情况。
4242

被折叠的 条评论
为什么被折叠?



