STL 中 lower_bound 与 upper_bound 与 二分查找
2015-11-01 12:07
316 查看
首先,先说明 lower_bound 与 upper_bound 的含义。对于区间 [first,last) 内的元素:
1.lower_bound :寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都满足 *j < value
2.upper_bound:寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都不满足 *j > value
示例:
序列: 1,2,3,5,6
3 的 lower_bound : 3。3 的 upper_bound : 5
4 的 lower_bound : 5。4 的 upper_bound : 5
实现:
使用二分查找法找到对应的位置,重点是 lower_bound 与 upper_bound 判断之间的区别,lower_bound 要找到第一个不小于 value 的元素,因此将所有小于等于 value
的值划分到左区间;upper_bound 要找到第一个大于 value 的值,因此将所有大于等于 value 的值划分到右区间。注意划分左右区间时,刚好抹去了中间的元素。这是为了避免死循环。具体代码如下:
*注意二分区间的划分:左区间:len = half,右区间:len = len - half - 1 ,(half = len >> 1),其中左右区间划分不包含中间元素(len_left + len_right = len - 1),但是当 中间元素 == value 时,左区间中若还有 value,则忽略中间元素不会影响结果;若左区间中无
value,则二分查找会找回到中间元素的前一个元素,又因为前一个元素小于中间元素,则会更新 first = ++middle,即返回超出区间的下一个元素(左区间的下一个元素即是中间元素)。因此,忽略中间元素仍然能找回来。
1.lower_bound :寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都满足 *j < value
2.upper_bound:寻找最远的 i,使得 [ first, i ) 中的每个迭代器 j 都不满足 *j > value
示例:
序列: 1,2,3,5,6
3 的 lower_bound : 3。3 的 upper_bound : 5
4 的 lower_bound : 5。4 的 upper_bound : 5
实现:
使用二分查找法找到对应的位置,重点是 lower_bound 与 upper_bound 判断之间的区别,lower_bound 要找到第一个不小于 value 的元素,因此将所有小于等于 value
的值划分到左区间;upper_bound 要找到第一个大于 value 的值,因此将所有大于等于 value 的值划分到右区间。注意划分左右区间时,刚好抹去了中间的元素。这是为了避免死循环。具体代码如下:
1.lower_bound:
template<class RandomAccessIterator,class T,class Distance> RandomAccessIterator __lower_bound(RandomAccessterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) { Distance len = _LXX::distance(first, last); Distance half; RandomAccessIterator middle; while (len > 0) { half = len >> 1; middle = first + half; if (*middle < value) //*middle < value, 所找的值一定在右半部分 { first = ++middle; len = len - half - 1; } else //*middle >= value, 所找的值在左半部分或者在 middle 处 len = half; //此处若是写为 len = half + 1, 则当 value == middle, len = 0 时将进入死循环 } return first; }
*注意二分区间的划分:左区间:len = half,右区间:len = len - half - 1 ,(half = len >> 1),其中左右区间划分不包含中间元素(len_left + len_right = len - 1),但是当 中间元素 == value 时,左区间中若还有 value,则忽略中间元素不会影响结果;若左区间中无
value,则二分查找会找回到中间元素的前一个元素,又因为前一个元素小于中间元素,则会更新 first = ++middle,即返回超出区间的下一个元素(左区间的下一个元素即是中间元素)。因此,忽略中间元素仍然能找回来。
2.upper_bound:
template<class RandomAccessIterator, class T, class Distance> RandomAccessIterator __upper_bound(RandomAccessIterator first, RandomAccessIterator last, const T &value, Distance *,random_access_iterator_tag) { Distance len = _LXX::distance(first, last); RandomAccessIterator middle; Distance half = 0; while (len > 0) { half = len >> 1; middle = first + half; if (value < *middle) { len = half; } else { first = middle + 1; len = len - half - 1; } } return first; }
相关文章推荐
- uva 10570——Meeting with Aliens
- android studio中api 23的消息推送机制
- [leetcode 246] Strobogrammatic Number
- Android团队
- 【Linux 内核】文件系统(概念篇)
- 【疯狂的架构】牛公司组织结构图一览:华为,阿里,腾讯,百度,新浪……
- Codeforces Round #328 (Div. 2) B. The Monster and the Squirrel
- HDU--3466(0-1背包+贪心/后效性)
- 【鸟哥的linux私房菜-学习笔记】Bash shell之管线命令
- ThinkPHP3.2.3中典型的ajax获取json数据方法
- codeforces #328 C. The Big Race
- 如何做到一个分数序列和
- python os目录和文件相关操作
- Coursera_Stanford_ML_ex7_K-means and PCA 作业记录
- 常见 门户布局
- JAVA基础1-JAVA入门和JDK的安装与配置
- 四校联训Round8心得体会
- SQLServer的数据类型
- Spring Spring mvc mybatis集成
- VisualStudio报错This function or variable may be unsafe的解决方法