当给定一个有序数组,而我们要在这个数组中查找某个数时,我们常常用从头到尾的排除法遍历寻找,但是这种方式及其低效,n个数的数组最差要找n次。而后面我们会知道,二分查找法则高效的多,最差要找log以2为低n的对数次,即如果有2^32个数,最差查32次就可得到结果。
所谓二分法,就是先用数组中间的数去和查找的数作比较,我们可以知道中间的数是大于还是小于要查的数,这样就能消去一般的数,而我们怎么去得到中间数的地址呢,我们应该使用查找区域最左边的地址和最右边的地址的平均数作为新的中间值的地址,之后再去比较,重复多次直到得出结果,下面我们用程序体会这种思想。
#define _CRT_SECURE_NO_WARNINGS 1//scanf所需
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//给出一个特定的数列
int a = 0;
int left = 0;
int right = 0;
printf("请输入一个要查找的数\n");
scanf("%d", &a);//输入一个想要查找的数a
int b = sizeof(arr) / sizeof(arr[0]);
left = 0;//left即左地址,地址最先是0
right = b-1;//right即右地址,地址为长度-1
int mid = (left + right) / 2;//求左右地址的平均值给mid,mid即为中间地址
while (left<=right) {//左右地址向中间逼近,左地址与右地址交错,则找不到a
if (arr[mid]< a) {//中间值在a左
left = mid + 1;//左地址对应数值及其左侧数值全部无效,将左地址更新为左地址相邻右侧地址
mid = (left + right)/2;//重新计算中间地址
}
else if (arr[mid]>a) {//中间值在a右
right = mid - 1;//右地址对应数值及其右侧数值全部无效,将右地址更新为右地址相邻左侧地址
mid = (left + right)/2;//重新计算中间地址
}
else if(arr[mid] == a) {
printf("找到了,地址是:%d", mid);
break;
}
else {
printf("没有找到");
}
}
return 0;
}
由以上程序可以看出,每次直接去中间值地址,用中间值与所查值比较,消去一半区域得到新的区间,在重新计算新区间的中间值地址,利用循环不断比较,左右地址不断向所查数字地址逼近,最终汇聚到一起,即为所查数的地址,若左右两地址想交错,则没有想查的数字