二分法查找易错点解析

    今天我们来探讨一下二分查找的易错点和错误情况。首先我们知道二分法查找适用于有序数组或者顺序表。本文简单的以有序数组做例子,依次查找0,1,2,3,4,5,6,7,8,9,10是否存在,存在则输出数字所在的数组下标值,不存在则输出-1来表示。

    下面我们来梳理一下二分法查找的逻辑。

二分法查找易错点解析_第1张图片 

    举例说明二分查找的形式如下所示:

 二分法查找易错点解析_第2张图片

    经过测试发现递归和非递归二分查找的结果相同,只有当改变二分查找的指针范围、循环结束条件及指针走向趋势,才可能会导致错误。下面我们来分步改变这三个条件,而其他条件不改变。从而得到可能会出现的错误类型。整理如下:

指针范围

循环结束条件

指针走向趋势

结果

 

左闭右开[)

left>=right

right=mid

可以得到正确结果

left>=right

right=mid-1

1,4,7找不到

left>right

right=mid

可以得到正确结果

left>right

right=mid-1

可以得到正确结果

 

左闭右闭[]

left>right

right=mid-1

可以得到正确结果

left>right

right=mid

可以得到正确结果

left>=right

right=mid-1

0,3,6,9找不到

left>=right

right=mid

存在的9找不到


   通过上表可以得出,左闭右开的二分查找,条件left>=right和right=mid-1不能同时存在;而左闭右闭的二分查找,循环结束的条件不能是left>=right。所以为了避免出错,不论指针范围,循环条件和指针走向趋势分别选择left>right和right=mid即可。

   希望能能给大家带来方便!再会!^_^


附加:给出二分查找的递归和非递归的代码如下:

int BinarySearch(type * a, size_t len, int x)//非递归二分法查找
{
	assert(a);
	int left = 0;
	int right = len;

	while(left <= right)
	{
		int mid = left+((right-left)>>1);//避免两数相加时的值超出整形表示范围
		if(x > a[mid])
		{
			left = mid+1;
		}
		else if(x < a[mid])
		{
			right = mid;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

 int BinarySearch2(type * a, size_t left, size_t right, int x)//递归二分法查找
{
	assert(a);

	if(left> right) return -1;
	else
	{
		int mid = left+((right-left)>>1);
		if(x > a[mid])
		{
			return BinarySearch2(a,mid+1,right,x);
		}
		else if(x < a[mid])
		{
			return BinarySearch2(a,left,mid,x);
		}
		else
		{
			return mid;
		}
	}
}

测试用例代码如下示:

int main()
{
    type a[10] = {0,1,2,3,4,5,6,7,8,9};
	cout<<"二分法查找非递归:"<


你可能感兴趣的:(编程知识)