二分查找

121 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

二分查找是什么

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
二分查找很多人都不陌生,它能高效的查找顺序数组里的特定值所在的位置。但有多少人能清楚地说出二分查找区间缩小过程中的边界要不要-1,while循环条件要不要加=号,二分查找有几种写法。 今天,我们就详细讲讲二分查找,让更多人弄清楚二分查找的正确写法。

易错点:边界处理

举个例子:假设下图(查找区间为左闭右开区间)想要查找4,当发现arr[mid] > 4时错将end转移到mid-1处,这样一来查找区间变为[0,4),不管怎么找都找不到4了,就会造成bug。 请添加图片描述 既然了解了错误原因,解决问题就变得简单了起来,根本上就是要重视边界处理,什么时候要加一什么时候要减一,还有跳出循环的条件中要不要等号,这些都一定要搞清楚。

示例

以下是二分查找(折半查找)的两种正确写法。大家可以作为参考。

//左闭右闭区间                                     
int BinarySearch1(int* a, int n, int x)
{
	assert(a);
	int begin = 0;
	int end = n - 1;

	while (begin <= end)
	{
		int mid = begin + ((end - begin) >> 1);//防溢出,>>运算符优先级很低,要再加一个括号
		if (a[mid] < x)
			begin = mid + 1;
		else if (a[mid] > x)
			end = mid - 1;
		else
			return mid;	 
	}
	return -1;
}
//左闭右开区间     
int BinarySearch2(int* a, int n, int x)
{
	assert(a);
	int begin = 0;
	int end = n;

	while (begin < end)
	{
		int mid = begin + ((end - begin) >> 1);//防溢出,>>运算符优先级很低,要再加一个括号
		if (a[mid] < x)
			begin = mid + 1;
		else if (a[mid] > x)
			end = mid;
		else
			return mid;
	}
	return -1;
}

细节要记得处理到位,大家加油!