⼆分查找的意义:
在⼀个升序的数组中查找指定的数字n,很容易想到的⽅法就是遍历数组,但是这种⽅法效率⽐较低。 ⽐如我买了⼀双鞋,你好奇问我多少钱,我说不超过300元。你还是好奇,你想知道到底多少,我就让 你猜,你会怎么猜?你会1,2,3,4...这样猜吗?显然很慢;⼀般你都会猜中间数字,⽐如:150,然 后看⼤了还是小了,这就是⼆分查找,也叫折半查找。
举例:在一个升序数组中查找指定的数值,找到了就返回下标
流程图如下:
首先我们在电脑画图板或者草稿本把思路理清楚,如上图,大致原理如下
先求数组中间元素下标int mid = (left + right) / 2;
1.当我们要查找7,就用数组中间元素arr[mid(4)]的值5与7比较,如果arr[mid](5)<7,那就要舍弃下标0到4的值,此时left下标的值就用mid=4然后再加上1的值替代:left = mid + 1;
2.如果arr[mid](8)>7,那就要舍弃下标7到8的值,此时right下标的值就用mid=7然后再减1的值替代:right = mid - 1;
3.left下标的值不断增大,rigft下标的值不断减小,当left <= right 时退出循环。
具体代码实现:
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);//输入要查找的值,假设是7
int sz = sizeof(arr) / sizeof(arr[0]);//求数组元素个数
int left = 0;
int right = sz - 1;
int flag = 0;//假设找不到
while (left <= right)
{
//int mid = (left + right) / 2;//当值过大时,不够精确,对其优化如下
int mid = left + (right-left) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
printf("找到了,下标是%d\n", mid);
flag = 1;
break;
}
}
if (!flag)
{
printf("找不到\n");
}
return 0;
}
注意!
当使用int mid = (left + right) / 2;时,当值过大时,可能出错,建议用int mid = left + (right-left) / 2;代替。
举例:
int main()
{
int a = 2147483646;
int b = 2147483646;
int avg = (a + b) / 2;//—2
//int avg = a+(b-a)/2;//2147483647
printf("%d\n", avg);
return 0;
}
原理如图
最后
道阻且长,行则将至;行而不辍,未来可期。
诸君共勉
点赞收藏加关注,有疑惑私信我!