二分查找
对一段有序序列进行二分查找关键字元素的想法很简单,但是充满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;
}
浙公网安备 33010602011771号