【二分查找】

本文详细介绍了二分查找的概念、代码实现过程以及其在有序数组中的高效性,包括时间复杂度分析和注意事项。尽管二分查找优点明显,但对数组有序性的要求限制了其实际应用范围。
摘要由CSDN通过智能技术生成

说不上为什么,我变得很主动...................................................................................................

目录

【前言】

一、【什么是二分查找】

二、【代码实现及原理】

2.1【原理分析】

2.2【代码实现】

2.3【注意】

三、【二分查找效率】

3.1【二分查找的优缺点】

3.2【二分查找的时间复杂度】

【总结】


【前言】

   介绍二分查找相关的知识。


一、【什么是二分查找】

  二分查找又叫折半查找,指的是在一组有序数据中查找是否存在某个具体数据时,通过使用这组数据的中间大小的数据来与被查找的数据进行比较,若小于(大于)中间数据,则取中间数据和起始数据(末尾数据)也就是最小数据(最大数据)之间的新中间数据再与被查找数据进行比较如此循环往复从而缩小查找范围,直到找到或者找不到。

这里用二分查找从1~9的数字里来查找3:

这里用一个例子来说明,比如我买了一个笔记本花了7元,然后我告诉你这个笔记本没有超过10元,接下来请你猜笔记本的价格,你会怎么猜?

可能有人会一个一个猜,也就是从1到10全猜一遍,这样你最少要猜一次,最多要猜十次。

也有人可能会蒙着猜,就是随便猜数字看看能不能蒙到,

这些办法都比较看运气而且效率不高。那么怎么猜才能更加高效呢?

这里就可以采用二分查找的思想,也就是猜1到10中间的数字就比如是6,然后我告诉你大了,也就是6小于笔记本的价格,接下来就用6和10中间的数字也就是8来来进行猜测,这时我会告诉你,大了,也就是笔记本价格比8要小这时再用6和8之间的数字7来比较,然后你就猜对了,这就是二分查找的基本思路。

二、【代码实现及原理】

2.1【原理分析】

二分查找算法的原理如下:
 1. 设置查找区间 [ low = 0;high= n;]
low和high指的是数组下标,其中low是第一个元素下标,high是最后一个元素下标。
 2. 若查找区[low, high]不存在则查找失败,若查找区间存在就进行步骤3。
 3. 取中间位mid = (low + high) / 2;比较 target(需要查找的数字)与 arr[mid],有以下三种情况:
   若 target < arr[mid],则high = mid - 1;查找在左半区间进行,重复步骤3
   若 target > arr[mid],则low = mid + 1;查找在右半区间进行,重复步骤3
   若 target = arr[mid],则查找成功,返回 mid 值;

2.2【代码实现】

例子:在数组【1,2,3,4,5,6,7,8,9,10】查找是否含有数字7

代码部分:

int main()
{
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr)/sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	int flag = 0;
	scanf("%d", &i);
	while (left<=right)
	{
		int mid = (right+left) / 2;//这里计算mid会出现问题我会在“注意”里说明。
		if (i < arr[mid])
		{
			right = mid - 1;
		}
		else if (i > arr[mid])
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了下标是%d\n", mid);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		printf("没找到");
	}
	return 0;
}

2.3【注意】

1.在计算mid时由于是用(left+right)/2来计算的,而当left和right都保证不超过整形能表示的最大值的情况下,但是mid却无法保证,也就是说,mid的值可能会超过整形能表示的最大值从而造成溢出现象。

解决办法:

bb4687e529c647108f461579fd9707f5.png

通过把right的多余部分分给left来实现,这里无论rigt和left谁大谁小都无所谓

代码:

int main()
{
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr)/sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	int flag = 0;
	scanf("%d", &i);
	while (left<=right)
	{
		int mid = left+(right-left) / 2;
		if (i < arr[mid])
		{
			right = mid - 1;
		}
		else if (i > arr[mid])
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了下标是%d\n", mid);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		printf("没找到");
	}
	return 0;
}

三、【二分查找效率】

3.1【二分查找的优缺点】

1.优点:二分查找更加高效,它的时间复杂度要小于遍历的时间复杂度。时间复杂度是log以2为底的N

图片展示:

0486f4fe23994d2f8eda9900bcde6c9e.gif

2.缺点:要求数组有序,查找的数量只能是一个,不能是多个查找的对象在逻辑上必须是有序的。

3.2【二分查找的时间复杂度】

二分查找是一种高效的查找方式,只要使用恰当,能极大的减少查找的时间。

二分查找最好时间复杂度是: 最好情况下只需要进行1次比较就能找到目标元素
二分查找最坏时间复杂度是:最坏情况就是查找不到目标元素,所需的时间复杂度为log以2为底的n。

具体如下:               

因为二分查找每次排除掉一半的不适合值,所以对于n个元素的情况:

一次二分剩下:n/2
两次二分剩下:n/2/2 = n/4
….........

......

...
m次二分剩下:n/(2^m)

在最坏情况下是在排除到只剩下最后一个值之后得到结果,即

n/(2^m)=1

所以由上式可得 : 2^m=n

进而可求出时间复杂度为: log2(n)

【总结】


二分查找虽然看着十分好用,但是他的致命缺陷就是要求数组有序,然而为数组排序本身就是一件消耗极大的事情,所以二分查找在实际当中的使用场景并不多


............................................................................................像这样的生活,我爱你,你爱我。

                                                                                                          ——————《简单爱》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值