题目
编写代码在一个整形有序数组中查找具体的某个数
要求:找到了就打印数字所在的下标,找不到则输出:找不到
方法
对于在整形有序数组中查找我们可以使用二分查找法,下面具体介绍一下该方法
例如,现在有一个有序数组arr[10]={1,2,3,4,5,6,7,8,9,10};我们想要查找该数组中的7这个数,应该怎么办呢?我们可以用循环遍历,让他一个一个的查找,直到找到对应的元素,但是这种方法显然过于粗暴和繁杂,不符合我们编译代码时要求简洁高效的原则,于是我们可以使用二分查找,二分查找其实就是让左右元素判断出中间元素,在通过中间元素向我们要查找的元素进行推进,当中间元素等于要找的元素时结束查找。与遍历不同的是,对于我们设定的左右元素,不在他们包括中的元素是不需要判断的,这样便节省了代码和时间。
首先,我们可以设置下标0为left,下标9为right,令(left+right)/2可以得到middle=4,也就是说中间元素为5,可是我们要找的元素7在5的右边,于是我们可以缩小范围——即将这里算出来的middle
后一位变成left,这样我们要查找的范围就变成了6-9,而6前面的元素便省去了查找的过程直接甩掉。
接着,我们继续将left和right进行运算,找到下一个middle元素8,我们可以看到8比我们要找的元素7更大,因此我们可以将right=middle-1也就是元素7,那么查找范围变成了6-7,我们继续查找,将这两个的中间值算出来后发现middle=6,我们要查找的元素在右边,那么left=middle+1,得到元素7,这下左右元素都等于7,运算后中间值也就等于7,找到了我们要找的元素。
明白了大概原理后,我们可以进行编译代码
代码
我们可以给定一个自定义函数,让解析过程都在自定义函数进行
int search(int arr[], int k,int sz)
{
int left = 0;
int right = sz - 1;
while (left<=right)//如果left>right根据left前面和right后面元素舍掉不计的原理,将没有元素可以查找
{
int mid = left + (right - left) / 2;
if (arr[mid] < k)
{
left = mid - 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else//如果中间值就是要查找的值,那么直接返回
{
return mid;
}
}
return -1;//如果没有找到返回一个不属于数组中的值
}
//二分查找是一个循环,这里面的代码只做到了一次查找,需要多次
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf_s("%d", &k);//输入想要查找的元素
int sz = sizeof(arr) / sizeo(arr[0]);//计算数组的长度
int ret = search(arr, k,sz);//将查找元素,数组长度,和数组传入函数中进行运算
if (ret == -1)
printf("找不到\n");
else
printf("找到了,下标是:%d\n", ret);
return 0;
}
同理,不用自定义函数也可以完成代码,只不过在判断是否能查找到元素时需要引入一个变量,如果查找到了值便设定变量为1,没有便为0,这样在判断时可以直接用变量判断。
注:怎么理解mid = left + (right - left) / 2?
为什么不用(left+right)/2呢?因为如果两个值足够大,加起来的值会造成数据溢出,形成错误,因此我们可以换个方法计算平均值
我们假如right的值比left大,那么我们将right比left大的值去掉一半,加到left上,就可以等于现在right的值,而现在两个元素的值,就是他们的平均值。