STL源码学习----lower_bound和upper_bound算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STL源码学习----lower_bound和upper_bound算法
STL中的每个算法都⾮常精妙,接下来的⼏天我想集中学习⼀下STL中的算法。
ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回⼀个⾮递减序列[first, last)中的第⼀个⼤于等于值val的位置。
ForwardIter upper_bound(ForwardIter first, ForwardIter last, const _Tp& val)算法返回⼀个⾮递减序列[first, last)中第⼀个⼤于val的位置。
lower_bound和upper_bound如下图所⽰:
1, lower_bound
这个序列中可能会有很多重复的元素,也可能所有的元素都相同,为了充分考虑这种边界条件,STL中的lower_bound算法总体上是才⽤了⼆分查找的⽅法,但是由于是查找序列中的第⼀个出现的值⼤于等于val的位置,所以算法要在⼆分查找的基础上做⼀些细微的改动。
⾸先是我修改数据结构课本上的⼆分查找实现的lower_bound算法:
int my_lower_bound(int *array, int size, int key)
{
int first = 0, last = size-1;
int middle, pos=0; //需要⽤pos记录第⼀个⼤于等于key的元素位置
while(first < last)
{
middle = (first+last)/2;
if(array[middle] < key){ //若中位数的值⼩于key的值,我们要在右边⼦序列中查找,这时候pos可能是右边⼦序列的第⼀个
first = middle + 1;
pos = first;
}
else{
last = middle; //若中位数的值⼤于等于key,我们要在左边⼦序列查找,但有可能middle处就是最终位置,所以我们不移动last,
pos = last; //⽽是让first不断逼近last。
}
}
return pos;
}
STL中的实现⽐较精巧,下⾯贴出源代码:
//这个算法中,first是最终要返回的位置
int lower_bound(int *array, int size, int key)
{
int first = 0, middle;
int half, len;
len = size;
while(len > 0) {
half = len >> 1;
middle = first + half;
if(array[middle] < key) {
first = middle + 1;
len = len-half-1; //在右边⼦序列中查找
}
else
len = half; //在左边⼦序列(包含middle)中查找
}
return first;
}
2, upper_bound
upper_bound返回的是最后⼀个⼤于等于val的位置,也是有⼀个新元素val进来时的插⼊位置。
我依然将⼆分查找略做修改:
int my_upper_bound(int *array, int size, int key)
{
int first = 0, last = size-1;
int middle, pos = 0;
while(first < last)
{
middle = (first+last)/2;
if(array[middle] > key){ //当中位数⼤于key时,last不动,让first不断逼近last last = middle;
pos = last;
}
else{
first = middle + 1; //当中位数⼩于等于key时,将first递增,并记录新的位置 pos = first;
}
}
return pos;
}
下⾯的代码是STL中的upper_bound实现:
int upper_bound(int *array, int size, int key)
{
int first = 0, len = size-1;
int half, middle;
while(len > 0){
half = len >> 1;
middle = first + half;
if(array[middle] > key) //中位数⼤于key,在包含last的左半边序列中查找。
len = half;
else{
first = middle + 1; //中位数⼩于等于key,在右半边序列中查找。
len = len - half - 1;
}
}
return first;
}。