lower_bound

lower_bound(begin, end, target)用来查找一个已排序的序列中[begin, end)第一个大于等于target的元素index。数组A如下:

value: 1, 2, 2, 3, 4, 5, 5, 6, 7

index: 0, 1, 2, 3, 4, 5, 6, 7, 8

这样的一个序列,如果查找5的lower_bound,返回的应该是第一个5即A[5]。下面是摘自cplusplus.com上的lower_bound代码

template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = distance(first,last);
while (count>)
{
it = first; step=count/; advance (it,step);
if (*it < val) { // or: if (comp(*it,val)), for version (2)
first = ++it;
count -= step+;
}
else count = step;
}
return first;
}

如果搜索对象只是数组的话还可以再简化一点:

count = last - start;
while (count > ) {
step = count/;
int* it = first + step;
if (*it < target) {
count = count - (step + );
first = it + ;
} else {
count=step;
}
}
return first;

基本情况: 当输入只有一个元素时,而该元素不是要查找的元素时返回last,即该元素的后一个位置

case: target=4

当在上图中的数组中找4的lower_bound时,第一次*it取到的值是4,因为这不是简单的二分搜索,而是要返回第一大于等于查找元素的位置,所以搜索不能在此时结束。但是可以确定5~7这一部分可以不用搜索了,因为当前至少有一个元素即*it是大于等于4了,因而缩小查找范围(count=step)。这个查找范围并不包括已找到的4,为什么是这样?分情况讨论:

1. 当前面的这个范围没有符合条件的数时,就会将范围最后的位置的后一位置返回,而此位置正好是4所在的位置(*it>= target时it所在的位置,它是符合查找条件的),其正好是lower_bound。

2. 当前面的这个方位含有符合条件的数时,此时当前的这个4就不是lower_bound,真正的lower_bound会在该区间内产生

case: target=5

当求5的lower_bound时,第一次找到中间元素时4,4<5,所以4和4前面的所有都不会含有5的lower_bound,因而下一次搜索只会在5~7这个区间进行,这个就和一个全新的问题一样了。

upper_bound

upper_bound用来在[begin, end)中找到第一个大于target的index

template <class ForwardIterator, class T>
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = std::distance(first,last);
while (count>)
{
it = first; step=count/; std::advance (it,step);
if (!(val<*it)) // or: if (!comp(val,*it)), for version (2)
{ first=++it; count-=step+; }
else count=step;
}
return first;
}

简化版本:

lower_bound:

         int lo = , hi = n;
// lower_bound
while (lo < hi) {
int mid = (lo + hi) / ;
if (A[mid] < target) {
lo = mid + ;
} else {
hi = mid;
}
} return lo;

upper_bound:

        lo = , hi = n;
// upper_bound
while (lo < hi) {
int mid = (lo + hi) / ;
if (A[mid] <= target) {
lo = mid + ;
} else {
hi = mid;
}
}
return lo;

就在判断条件上多了个等号

C++ STL:lower_bound与upper_bound实现的更多相关文章

  1. [STL] lower_bound和upper_bound

    STL中的每个算法都非常精妙, ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一 ...

  2. C++ STL lower_bound()和upper_bound()

    lower_bound()和upper_bound()用法 1.在数组上的用法 假设a是一个递增数组,n是数组长度,则 lower_bound(a, a+n, x):返回数组a[0]~a[n-1]中, ...

  3. STL源码学习----lower_bound和upper_bound算法

    转自:http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 先贴一下自己的二分代码: #include <cstdio&g ...

  4. STL lower_bound upper_bound binary-search

    STL中的二分查找——lower_bound .upper_bound .binary_search 二分查找很简单,原理就不说了.STL中关于二分查找的函数有三个lower_bound .upper ...

  5. STL中的lower_bound和upper_bound的理解

    STL迭代器表述范围的时候,习惯用[a, b),所以lower_bound表示的是第一个不小于给定元素的位置 upper_bound表示的是第一个大于给定元素的位置. 譬如,值val在容器内的时候,从 ...

  6. STL 源码分析《5》---- lower_bound and upper_bound 详解

    在 STL 库中,关于二分搜索实现了4个函数. bool binary_search (ForwardIterator beg, ForwardIterator end, const T& v ...

  7. STL源码学习----lower_bound和upper_bound算法[转]

    STL中的每个算法都非常精妙,接下来的几天我想集中学习一下STL中的算法. ForwardIter lower_bound(ForwardIter first, ForwardIter last,co ...

  8. [转] STL源码学习----lower_bound和upper_bound算法

    http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html PS: lower_bound of value 就是最后一个 < ...

  9. STL之std::set、std::map的lower_bound和upper_bound函数使用说明

    由于在使用std::map时感觉lower_bound和upper_bound函数了解不多,这里整理并记录下相关用法及功能. STL的map.multimap.set.multiset都有三个比较特殊 ...

  10. STL中的二分查找——lower_bound 、upper_bound 、binary_search

    STL中的二分查找函数 1.lower_bound函数 在一个非递减序列的前闭后开区间[first,last)中.进行二分查找查找某一元素val.函数lower_bound()返回大于或等于val的第 ...

随机推荐

  1. C++多线程编程二

    1. 死锁与解锁: #include <iostream> #include <thread> #include <mutex> using namespace s ...

  2. 总结day7 ---- 函数的内容 ,初识,返回值,进阶(一)

    内容大纲: 一: 函数识别 二: 函数的结构 三: 函数的返回值, 四: 函数的参数 五: 动态参数 六: 形参的顺序 七: 名称空间 八: 作用域 九: 加载顺序和取值顺序 十: 内置函数 十一: ...

  3. 总结day3 ---- 进制转换,字符串切片,字符串常用方法.,for 循环,

    前情提要: int 的相关操作 进制转换 bit_lenth() str 的索引,以及常用的相关方法 for 循环 索引 切片 相关方法 一  : int 的相关操作 int 主要用于生活中的计算问题 ...

  4. SPI 用户空间的读写操作

    spi_device 虽然用户空间不需要直接用到spi_device结构体,但是这个结构体和用户空间的程序有密切的关系,理解它的成员有助于理解SPI设备节点的IOCTL命令,所以首先来介绍它.在内核中 ...

  5. Objective-C 之category

    参考资料:iOS设计模式——Category Category Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的. 相当于Swift中的功能扩展(extension). 新添加的 ...

  6. hdu 1233 还是畅通工程 并查集or最小生成树

    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路 ...

  7. 角色用户权限RBAC

    关于角色.用户.权限的表设计,已经成为经典中的经典,到处都在用,这里只是收录一下: 角色表:{role_id,role_name} 用户表:{user_id,user_name} 权限表:{permi ...

  8. dip,px,sp区别及使用场景

    1.区别 dip(device independent pixels)——设备独立像素:这个和设备硬件有关,一般哦我们为了支持WCGA.HVGA和QVGA推荐使用这个,不依赖于像素.等同于dp. px ...

  9. mix使用本地依赖

    在看elixir程序设计,书中讲到依赖设置,但是都是要联网,自己希望可以下载到本地电脑硬盘,然后项目要使用就用本地的,不要每次都要下载,因为天朝下载真的不稳 官方看到文档 {:deps_name,pa ...

  10. linux下wc功能的简单实现

    1.代码来源:自己编写 2.运行环境:linux终端 3.编程语言:c/c++语言 4.bug:未发现 5.当前功能:可以统计字符的字符数.行数.单词数 6.使用方法:wc -l 文件名-->统 ...