在一个有序数组中查找具体的某个数字
二分查找只能适用于有序的数组
首先,我们先给定一个数组 arr[10]={1,2,3,4,5,6,7,8,9,10}
如图所示
因为下标都是从0开始的,所以我们定义数组的左下标为 left = 0
如果我们不知道数组中元素的个数,那么我们便无法知道右下标,但是通过计算得到数组中元素的个数。
sizeof 可以计算数组所占空间的大小,所以 元素个数 = sizeof( arr[] )/sizeof( arr[0] ),即数组所占总空间大小/一个元素所占空间大小。注意arr[0]表示的是数组中的第一个元素,所以sizeof( arr[0] )是指一个元素所占空间的大小。那么数组的右下标为 right = sizeof( arr[] )/ sizeof( arr[0] ) - 1.
如图所示
那么我们所寻找元素下标的范围就在 left ~ right 之间,包含 left 与 right 。
那么中间元素的下标 mid = ( left + right ) / 2 即 mid = ( 0 + 9 ) / 2 = 4
假设我们查找的数字为 k
那么下表 mid 所对应的元素是 arr[4], 如果 arr[4] < k,说明元素 k 的下标在 4 ~ right 之间,不包含4,如果arr[4] < k,那么元素k的下标范围是 left ~ 4 之间,不包含4。
假设 k = 7 , arr[4] < 7, 所以查找元素在元素arr[4]d的右边
此时 left = mid + 1
如图
然后根据新的 left 与 right 求出 新的 mid = ( 5 + 9 ) / 2 = 7(下标)
如图
那么 arr[7] > 7(元素),说明在 left ~7(下标)之间,不包含 7 ,right = mid - 1
如图
然后新的中间元素下标 mid = (5 + 6 ) / 2 = 5, 此时arr[5] < 7, 则 left = mid + 1 = 6
如图
新的 mid = ( 6 + 6 ) / 2 = 6, 此时 arr[6] = 7 ,所以找到了
总结一下 :
① 确定数组的左右下标 left 和 right
② 根据 left 与 right 确定中间下标 mid
③ 根据 mid 锁定元素并与查找的元素比较,确定新的查找范围即新 left 和 right
④ 重复 ②③步骤,直到找到查询元素为止
废话不多说,上代码
#include<stdio.h>
int main()
{
int k = 7;
int arr[] = {1,2,3,4,5,6,7,8,9,10 }; //定义一个数组
int left = 0; //左下标
int right = sizeof(arr) / sizeof(arr[0]) - 1; //右下标
int mid = 0; //中间元素的下标
while (left <= right) //只有当left <= right 时,才存在元素与 所查元素比较
{
mid = (left + right) / 2; //求得中间元素下标
if (arr[mid] == 7) //当下标锁定元素与所查找元素相等时,跳出循环
{
break;
}
else if (arr[mid] > 7) //当下标锁定元素大于所查找元素时
{
right = mid - 1; //确定新的右下标
}
else
{
left = mid + 1; //当下标锁定元素小于所查找元素时,确定新的左下标
}
}
//此时有两种情况,一种是在循环过程中找到了,break跳出循环来到这
//另一种是循环结束,没找到,来到这,此时left > right
if (left <= right) //用来判断是哪一种情况
{
printf("找到了,下标是%d \n",mid);
}
else
{
printf("没找到\n");
}
return 0;
}
下面这个用 flag 作为标记来判断是否找到,替代了 (left <= right)
#include<stdio.h>
int main()
{
int k = 7;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; //定义一个数组
int left = 0; //左下标
int right = sizeof(arr) / sizeof(arr[0]) - 1; //右下标
int mid = 0; //中间元素的下标
int flag = 0; //作为一个标记
while (left <= right) //只有当left <= right 时,才存在元素与 所查元素比较,用到了while循环
{
mid = (left + right) / 2; //求得中间元素下标
if (arr[mid] == 7) //当下标锁定元素与所查找元素相等时,跳出循环
{
flag = 1; // 当找到了flag 变为1,否则flag 为 0
break;
}
else if (arr[mid] > 7) //当下标锁定元素大于所查找元素时
{
right = mid - 1; //确定新的右下标
}
else
{
left = mid + 1; //当下标锁定元素小于所查找元素时,确定新的左下标
}
}
//此时有两种情况,一种是在循环过程中找到了,break跳出循环来到这
//另一种是循环结束,没找到,来到这,此时
if (flag == 1) //用以判断是否找到
{
printf("找到了,下标是%d \n", mid);
}
else
{
printf("没找到\n");
}
return 0;
}