二分查找

对一段有序序列进行二分查找关键字元素的想法很简单,但是充满Tricky。

关于二分上下界,二分时的整除性,二分中止的条件,这些都值得细细地斟酌。

一般来说,二分查找可以用来解决两类问题。

1. 查找元素el是否在数组A中,返回查找到的位置Pos或-1(未找到)
2. 找出满足条件的元素的范围
(1)查找元素el,返回位置Pos,使得从Pos到结束的元素都大于等于el,且Pos之前的元素都小于

el,即A[Pos..n-1]>=el && A[0..Pos-1]<el
(2)上同(1),但使得A[Pos..n-1]>el && A[0..Pos-1]<=el

C++ STL中也实现了这三个方法。分别是binary_search, lower_bound, upper_bound

 

我很想找一种通用的结构,在查找元素的范围和二分中止条件上,统一的实现这两类问题,但始终

未能解决。

有待研究Knuth的TAOCP Volume 3。

1. binary_search
查找是否存在元素el。我们要查找的元素在[0..n-1]的范围内,二分中止的条件是 上界越过下界

int BinarySearch(int X[], int l, int r, int el)
{
	int mid;
	
	while (l<=r)
	{
		mid = (l+r)>>1;
		if (X[mid]==el) return mid;
		if (X[mid]>el) r = mid-1;
		else l = mid+1;
	}
	return -1;
}

2. lower_bound和upper_bound

查找元素的范围。仿照STL的方式,设定范围[First..end),即XXXerBound(Array, 0, N, el);由于整数的整除性,中点mid 离低处端点l 近,所以退出条件是l==r,且始终保证r 是满足条件的最后一个元素。

int LowerBound(int X[], int l, int r, int el)
{
	int mid;

	while (l<r)
	{
		mid = (l+r)>>1;
		if (X[mid]>=el) r = mid;
		else l = mid+1;
	}
	return r;
}

int UpperBound(int X[], int l, int r, int el)
{
	int mid;

	while (l<r)
	{
		mid = (l+r)>>1;
		if (X[mid]>el) r = mid;
		else l = mid+1;
	}
	return r;
}

posted on 2011-02-06 20:48  K.I.S.S.  阅读(223)  评论(0)    收藏  举报

导航