折半法(二分)搜索有序数列元素下标及数组传参问题

对于有序数列而言,如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
来源:知乎
见知甚少如若有错误之处请指正。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值