二分查找法

1、定义:一种用于在有序数组中查找某一特定元素的搜索算法。

2、过程:如一个正序数组,从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定的元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果某一步骤数组为空,则代表找不到,这种算法每一次搜索都使搜索范围缩小一半。

在这里插入图片描述

3、时间复杂度:最优时间复杂度为O(1),平均复杂度和最坏复杂度均为O(logn)。

4、空间复杂度:若使用迭代,则空间复杂度为O(1);若使用递归,则空间复杂度为O(logn)。

5、程序:

用于搜索数据是否存在于数组内

int binary_search(int start, int end, int key) {
  int ret = -1;  // 未搜索到数据返回-1下标
  int mid;
  while (start <= end) {
    mid = (start + (end - start))/2;  
    // 直接平均可能会溢出,所以用这个方法
    if (arr[mid] < key)//若待处理数大于中间值,则向右缩小
      start = mid + 1;
    else if (arr[mid] > key)//若待处理数小于中间值,则向左缩小
      end = mid - 1;
    else {  // 最后检测相等是因为多数搜索情况不是大于就是小于
      ret = mid;
      break;
    }
  }
  return ret;  // 单一出口
}

解释一下mid中间值的式子:一种直观的方法是用 mid = (start + end)/2 来计算中间值,这样就是简单地取区间的平均值。但是这种方法有一个潜在的问题,就是当 start 和 end 的值都很大时,它们的和可能会超过 int 类型的最大值,导致计算结果发生溢出,从而得到错误的中间值。例如,如果 start = 2^30 - 1,end = 2^30,那么 start + end = 2^31 - 1,这个值已经超过了 int 类型的最大值 2^31 - 1,所以计算结果会变成一个负数,而不是正确的中间值。

为了避免这种溢出的风险,我们可以用另一种方法来计算中间值,就是用 mid = ((end-start)+start)/2。这样就是先计算区间的长度,然后再加上区间的左边界,这样就可以保证计算结果不会超过 int 类型的范围,而且和直接取平均值的方法是等价的,因为 start + (end - start)/2 = (start + end)/2。这种方法的优点是不管 start 和 end 的值有多大,它们的差值能在 int 类型的范围内,而且加上 start 之后也不会超过 int 类型的范围,所以可以避免溢出的问题。

或是用于搜索待处理数据在有序数组中的下标或位置:

int bisearch(int a[], int low, int high, int key)
//二分查找去找到key在有序数列a[]中应该插入的位置
{
	while(low<=high)
	{
		int mid=(low+(high-low))/2;
		if(a[mid]==key) return mid;
		else if(a[mid]<key) low=mid+1;
		else if(a[mid]>key) high=mid-1;
	}
	return low;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值