今天学习到了二分查找,也叫折半查找。之前已经接触了这个知识,但那时候只是知道了原理,并没有实现代码的输出。今天完成了代码的输出,使用二分查找查找你想查找的数。
注意折半查找只适用于有序的数组。
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int k = 0;
printf("请输入你想查找的数字:");
scanf("%d", &k);
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
int flag = 0;
while (left <= right) {
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 (0 == flag) {
printf("找不到该数字\n");
}
return 0;
}
折半折半,顾名思义需要找到中间那个数加上左右俩个数进行配合,一半一半的减少查找范围,所以叫做折半查找,具体过程是这样的。
![](https://i-blog.csdnimg.cn/blog_migrate/3f138e187db33adf9b97caa0bf5ee1ac.png)
首先我们先设置好左右俩边,才能去找到中间的数值。这里我采用的sizeof去求数组具体包含多少数据,虽然我可以一个个去数到底有几个数据,目前来说这样可能更加便捷。但是你以后如果要处理成百上千的数据的时候,不可能也一个个这样去数吧,所以我们现在这里养成这样的好习惯,这样才会让你的代码通用性,实用性,可维护性更强一些。不至于增加几个数据,你就得改代码了。
![](https://i-blog.csdnimg.cn/blog_migrate/a7592912b9e3d7e0f7217e312371231d.png)
这里的设left = 0,应该都知道数组的下标是从0开始的,就不多解释了。
再接着到设置mid了,这里有个小细节可以注意一下。
int mid = (left + right)/2;
普通的是不是这样就可以找到mid了。这样目前也没什么错误,但是我们要注意了,已知我们的int数据是有上限的,如果left 和right的数据相加超过这个限制的时候,就会导致一部分的数据丢失。还是刚才的话,现阶段可能不会造成这个影响,但你以后处理的数据就不好说了。还是一个好习惯的问题。那么我们该如何解决这个问题呢?很简单:
int mid = left + (right - left) / 2;
这样看可能会有点抽象,我们把它转化成模型看一下。
![](https://i-blog.csdnimg.cn/blog_migrate/8216fe38abfde83c988676aee8be6484.png)
可以看到一开始的right和left的状态是这样的,它们直接相加在一起就超出界限了,那么该如何找到它们的中间值呢。可以看到:
![](https://i-blog.csdnimg.cn/blog_migrate/100f4c28156314fe448f96c73d37c919.png)
如图所示,我把right多出来的那一部分求出来,也就是俩个相减。再把这一部分的一半加到left上面是不是right和left就相等了,实现了不用加法的平分,找到mid。额外说一点因为我这里采用的是循环,left或者right会不断的改变,会出现到left大于right的,这个时候mid一样是可以找到的,这就是关于数学部分了,我就不多赘述了。
准备过程结束,接着就是查找了。第一种情况就是你查找的数字要大于mid的值,因为数组是有序的,所以你查找的值如果存在就一定在mid的右边,这个时候你原来的left的值就要发成改变了,变到mid的右边,也就是left = mid +1 ;然后再重新找到mid值。如图:
![](https://i-blog.csdnimg.cn/blog_migrate/ea2c88f4f566e869f41a3b608f0ebfcd.png)
你可能会有点疑惑,为什么mid指向7,而不是8。因为mid是int型,而left和right的下标相除所得是6.5,你只能读取到6,所以指向的是7。接下来再重复刚才的操作,如果找到了就用brake跳出循环,同时把flag赋为1,让程序判断你是否成功。如果失败,那么flag值还是0,就会显示没有找到这个数。
![](https://i-blog.csdnimg.cn/blog_migrate/35d7cb2b06a7d2ea2b157cf9d1b55591.png)
这个是mid的值大于你要找的值的情况,大同小异。