对于有序数列而言,如arr[]=1,2,3,4,5,6,7,9,10这组数列,可以通过中间元素和所求数字大小比较反复筛选。来大大减少运算量,找到目标元素,从而求出其下标值。
若要数组是否有元素是7,若有输出它得下标。
先求出sizeof函数求出数组得元素个数,然后减1得到最大下标值,也就是10得下标,定义为right
第一个0下标开始,定义left
第一次求平均值mid下标对应元素5,比较后小于7,那么right不变,left=mid+1,将范围缩小进而求值,反之若小于7那么right=mid-1.
当解决方案写好后,将其定义一个函数,然而当数组名作为形参传入函数时,函数对于数组得接收需要定义指针来接,这时arr表示得是数组元素得首地址(注)指针进入函数内部以后sizeof(arr)(不同于在main函数中sizeof可以直接计算全部大小)计算结果在32机器里指针所占位数恒为4,所以无法在函数内部判断数组大小。
程序如下
int binary_search(int arr[], int key, int sz)//这里arr[]是指针,相当于int*arr,特有的
{
int left = 0;
int right = sz - 1;//此为数组元素的下标最值
while (left <= right)//此处用折半法求数,每次缩小边界值直至相等(无论数组元素在是奇数或者偶数的情况下该条件都成立)
{
int mid = left + (right - left) / 2;//此处求出检验的中间下标,这个表达式不能出现在语句外部,一定要细心 关于循环应用的变量是否应该在内部或者外部的问题,
if (arr[mid] == key)
{
return mid;
}
else if (arr[mid] > key)
{
right = mid - 1; //此方法不会排除边界元素,会逐一寻找,每次排除的是下标为mid的元素
}
else if (arr[mid] < key)
{
left = mid + 1;
}
}
return -1;//当函数内部的while循环结束 也就是条件不满足的时候,意味着没有找到,此时返回-1作为主函数提取返回值检验的标准
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int key = 0;
scanf("%d", &key);
int sz = (sizeof(arr) / sizeof(arr[0]));//测量数组长度
int ret = binary_search(arr,key,sz);
if (-1== ret)
{
printf("没找到");
}
else
{
printf("找到了,下表为%d", ret);
}
system("pause");
return 0;
}
(注):转载自知乎
`arr`是个数组变量,所以它其实不是一个指针,而是栈一段长度为三个 int 的连续地址空间。
但是 C 语言规定了 arr 作为值引用的时候,表示的是这段空间的首地址。
&arr C 也定义了它是合法的,取值也只能是这段连续空间的首地址(还能是什么呢?)。
arr[0],是数组 arr 的第一个元素,它的地址当然还是这段空间的首地址
需要注意的是,如果 p 是一个指针,比如 int*,&p 和 p 在类型上和数值上都是不等的。
作者:邓毅链接:https://www.zhihu.com/question/30177303/answer/47279605
来源:知乎
见知甚少如若有错误之处请指正。