折半查找算法(二分查找法)

一、前言

二分查找算法是一个很常见到的一种找到指定数字的方式,希望看完这篇文章后可以带你理解二分查找如何实现和原理。

二、原理


二分查找二分查找(Binary Search)算法,也叫折半查找算法。二分查找的原理很简单,比如

说:有一件衣服的价格的范围是1~500,让我们去猜他的价格,我们总是会去找中间的那个值去

猜,而是从1开始一直往后猜,这样的效率就太低了,在这种情况下我们就引入了二分查找,二分

查找是针对有序的数据集合(这里是使用二分查找的前提条件),每次通过跟区间的中间元素去比

较,将要查找的区间每次都缩小到原来的一半,直到找到这个元素为止,或者当这个区间为0的时

则意味着,找不到这个元素

为了方便我们理解,我们以图中的数组为例1,2,12,13,23,27,35,40,45,70,我们以查找35为例,画了了一张简易图(忽略图画的不好这个细节),其中left代表左下标,right代表右下标,mid表示中间值下标
在这里插入图片描述 二分查找就如图中所示,如果中间值大于要查找的值,则往数组的左边继续查找,改变左边的范围,如果中间值小于要查找的值,则往数组的右边继续查找,改变右边的范围,直到找到这个元素或者,区间为0为止

三、代码的实现

二分查找可以使用循环和递归来进行实现,我们来分别看一下循环和递归如何实现

1、循环

int bin_search(int arr[], int left, int right, int key)
{
	while (left <= right)
	{
		int mid = left + (right - left) /2;//计算中间下标
		if (arr[mid] < key)//大于给定值,向右边找
			left = mid + 1;
		else if (arr[mid] > key)//小于给定值向左边找
			right = mid - 1;
		else
			return mid;//等于给定值返回下标
	}
	return -1;//找不到返回-1
}
int main()
{
	
	int key = 0;
	scanf("%d", &key);
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;//计算right的下标位置
	int num = bin_search(arr,left,right,key);
	if (num == -1)
		printf("找不到\n");
	else
	{
		printf("找到了\n");
		printf("下标为 %d", num);
	}
	return 0;
}

上述写法是采用[left, right] 区间的写法,左闭右闭的写法,两边都可以去得到,二分查找在循环中还存在一种[left, right)的写法,形式大同小异,只是right的位置取不到了,因此处理会做出些许的改变

int main()
{

	int key = 0;
	scanf("%d", &key);
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]);//计算right的下标位置但是取不到right
	int flag = 0;
	while (left < right)//因为right取不到所以不能带等号
	{
		int mid = left + (right - left) / 2;
		if (arr[mid] < key)
			left = mid + 1;
		else if (arr[mid] > key)
			right = mid;//因为right取不到因此right=mid 这里可以用数学里的方式去理解 比较好理解
		else
		{
			printf("找到了\n");
			printf("下标为 %d", mid);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		printf("找不到\n");
	}

}

二分查找的实现是比较的简单的,需要注意但是中间值的计算,一种是(right+left)/ 2这种计算方式会出现超出所定义数据类型的范围,即是除以2之后的值是在范围内,也会出错,因此方法一会出现溢出的风险,方法二是 left+(right-left)/2这种计算方式与第一种计算的结果相同,但是就没有溢出的问题,它总是保证了生成的mid大于left小于right

2、递归

int bin_search(int arr[],int left,int right,int key)
{
	if (left <= right)
	{
		int mid = left + (right - left) / 2;//找出中间下标
		if (arr[mid] > key)
			return bin_search(arr, left, mid - 1, key);
		else if (arr[mid] < key)
			return bin_search(arr, mid + 1, right, key);
		else
			return mid;
	}
	else
		return -1;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;
	int key = 0;
	scanf("%d", &key);
	int num = bin_search(arr,left,right,key);
	if (num == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了\n");
		printf("下标为 %d", num);
	}
	return 0;
}

四、总结

以上就是本人目前对于二分查找的全部理解了,认为二分查找还是有诸多的局限性的,使用的条件比较的苛刻,但是使用起来比较的方便。

感谢大家可以看到这里,本人小白一个,如果有错误,欢迎各位大佬前来指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值