今天我们来分一道小题:折半查找目标数
在一个有序数组中查找具体某个数字n
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9
int k = 17;//k是要查找的数字
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int flag = 0;//
for (i = 0; i < sz; i++)
{
if (k == arr[i])
{
flag = 1;
printf("找到了,下标是:%d\n", i);
break;
}
}
if (flag == 0)
printf("找不到\n"); //结果:找不到
return 0;
}
首先,我最容易想到的就利用for循环,if语句判断,逐个去检验是否自己目标的数字。但是,这个算法有一个不足。假如n位置非常靠后,就会导致我们运算次数很多,效率变低。那么有什么方法可以改进这个不足么?接下里就是我们的重头戏———二分法!
二分法,通过将区间减半,逐步逼近目标数字,从而找出目标数字
首先我们将数组左端的元素定义为left,最右端的元素定义为right。根据左端元素的下标和右端元素的下标求出中间元素的下标mid。
第二步,判断目标数字n是在左侧还是右侧(n<mid--左侧,n>mid--右侧)
第三步,若目标数组在mid左侧,把mid-1赋给right;反之将mid+1赋给left。若俩条件都不满足,着目标数就是mid。
通过多次将区间折半,我们的区间就会越来趋近我们的目标数字。
思路就是这样。接下来,我们看下代码是如何实现的
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9
int k = 17;//k是要查找的数字
int i = 0;
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) //当目标数在mid的右边
{
left = mid + 1; //改变left 区间变成 ——》【mid,right】
}
else if (arr[mid] > k) //当目标数在mid的左边
{
right = mid - 1; //改变right 区间变成 ——》【left,mid】
}
else
{
printf("找到了,下标是:%d\n", mid);
flag = 1;
break;
}
}
if (flag == 0)
printf("找不到\n");
return 0;
}
这个题很有意思,希望各位读者可以多多体会,希望对各位有所帮助。感谢各位i读者