二分查找算法(递归+非递归)

二分查找是针对有序序列来说的,在有序序列中使用二分查找能大大提高查找效率。

二分算法步骤

前提:有序数组中查找关键词所在的位置

① 首先确定整个查找区间的中间位置 mid 

② 用待查关键字key值与中间位置的关键字值进行比较;

若相等,则查找成功

若大于,则在后(右)半个区域继续进行折半查找

若小于,则在前(左)半个区域继续进行折半查找

③ 对确定的缩小区域再按折半公式,重复上述步骤。

 

中间位置mid的表示:

(1)简单的写法

mid = (start + end) / 2

 但这种写法有个缺点:mid可能会溢出。

我们可以举一个简单的例子来证明这一事实。

比如,当start = 1000  ,end = INT_MAX。INT_MAXint数据类型可以存储的上限。这时start + end的和就溢出了。

(2)保险的写法

mid = start + (end - start) / 2

这样的写的好处大概有两个:

第一 :不会产生溢出

第二 :从通用性考虑,适用于对指针或者迭代器的操作。如果start和end同时是指针或者同时是迭代器时无法编译通过,因为俩指针或者俩迭代器运算不支持相加运算,只支持相减运算。

为什么指针和迭代器运算不支持相加运算,只支持相减运算?

我发现网上很少提及这个问题的原因。本人认为原因是这样的:两个迭代器相加,或者两个指针相加后所表示的位置对于vector容器就越界了,失去的意义。但是相减就可以,位置还在容器之中。

(3)(2)的另一种写法

mid = start + ((end - start) >> 1)

 这种写法和(2)一样。

“>>”:表示向右移。value >> num:即value的二进制数整体向右移num位,表示在十进制上就是value除以2的num次方,value >> 1就是value 除以2。

“<<”:表示左移。value << num,就是指value的二进制形式整体向左移动num位,表示在十进制上就是value乘以2的num次方,value << 1就是value乘以2。

故(end - start) >> 1,即为(end - start) / 2。

 

二分查找算法

非递归写法:

/**
 *Copyright (c) 2019 Young Fan.All Right Reserved.
 *Author: Young Fan
 *Date: 2019.04.26
 *IDE: Visual Studio 2017
 *Description:
 */

#include <iostream>

using namespace std;

int binarySearch(int numbers[], int length, int target) {

	int length_ptr = sizeof(numbers) / sizeof(int);
	cout << length_ptr << endl;//输出为1,sizeof会把从主函数中传进来的字符数组当作是指针来处理。
					//指针的大小又是由机器来决定,32位编译器指针变量的大小为4字节,64位编译器指针变量的大小为4字节
	if (length == 0)
		return -1;
	int start = 0, end = length - 1;
	while (start <= end) {
		int mid = start + (end - start) / 2;
		if (numbers[mid] == target)
			return mid; //查找到了则返回数据数组的下标
		else if (numbers[mid] > target)
			end = mid - 1;
		else
			start = mid + 1;
	}
	return -1;
}

int main()
{

	int numbers[] = { 1, 2, 3, 4, 5, 6, 7};  //有序的
	int length = sizeof(numbers) / sizeof(int); //n得7
	cout << "length = " << length << endl;
	int a = binarySearch(numbers, length, 7); //返回数据数组的下标

	cout << a << endl;

	return 0;
}

递归写法:

int binarySearch(int[] a, int start, int end, int target) {
        if(start > end)
            return -1;
        int mid = start + (end - start) / 2;
        if(a[mid] == target)
            return mid;
        else if(a[mid] > target)
            return binarySearch(a, start, mid-1, target);
        else
            return binarySearch(a, mid+1, end, target);
}

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值