在 STL 库中,关于二分搜索实现了4个函数。

bool binary_search (ForwardIterator beg, ForwardIterator end, const T& value)

判断 [beg, end) 中是否存在 value 的值。

ForwardIterator

lower_bound (ForwardIterator beg, ForwardIterator end, const T& value)

ForwardIterator

upper_bound (ForwardIterator beg, ForwardIterator end, const T& value)

搜寻第一个或者最后一个可能位置。

具体是什么意思呢?

1. lower_bound 指的是 返回第一个 ”大于等于 value“ 的元素位置。

另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的第一个位置

2. upper_bound 指的是 返回第一个 “大于 value ” 的元素位置;

另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的最后一个位置

举个例子: 1 2 2 3 4 5

value = 2: 则 lower_bound 返回的位置是 第 1 个位置;

upper_bound 返回的位置是 第 3 个位置。

大家可以看到一个很有意思的性质:

upper_bound - lower_bound = 数组中 value 的个数



下面我们来研究下 lower_bound 和 upper_bound 的实现。

以下是我按照源码改写的一个版本:

// return the first element which >= x
int LowerBound(int *a, int n, int x)
{
int left(0), right(n-1), mid; while(left <= right){
mid = left + ((right - left) >> 1);
if(a[mid] < x){
left = mid + 1;
}
else{
right = mid - 1;
}
} return left;
} // return first element which > x
int UpperBound(int *a, int n, int x)
{
int left(0), right(n-1), mid; while(left <= right){
mid = left + ((right - left) >> 1);
if(a[mid] <= x){
left = mid + 1;
}
else{
right = mid - 1;
}
} return left;
}

大家知道,在 STL 库中,区间一般采用半闭半开区间 [begin, last),

这种做法的好处是 last - begin 就是区间元素的个数。

以下是 STL 中的源码:

template <class _ForwardIter, class _Tp, class _Distance>
_ForwardIter __lower_bound(_ForwardIter __first, _ForwardIter __last,
const _Tp& __val, _Distance*)
{
_Distance __len = 0;
distance(__first, __last, __len);
_Distance __half;
_ForwardIter __middle; while (__len > 0) {
__half = __len >> 1;
__middle = __first;
advance(__middle, __half);
if (*__middle < __val) {
__first = __middle;
++__first;
__len = __len - __half - 1;
}
else
__len = __half;
}
return __first;
}

lower_bound的一个应用:

最长递增子序列问题:分析见  http://blog.csdn.net/shoulinjun/article/details/13775177

代码如下:

int LIS(int *a, int n)
{
if(n <= 0) return 0;
vector<int> maxV;
maxV.push_back(a[0]);
for(int i=0; i<n; ++i)
{
if(a[i] > *maxV.rbegin())
maxV.push_back(a[i]);
else
*lower_bound(maxV.begin(), maxV.end(), a[i]) = a[i];
}
return maxV.size();
}

STL 源码分析《5》---- lower_bound and upper_bound 详解的更多相关文章

  1. ZRender源码分析5:Shape绘图详解

    回顾 上一篇说到:ZRender源码分析4:Painter(View层)-中,这次,来补充一下具体的shape 关于热区的边框 以圆形为例: document.addEventListener('DO ...

  2. Jvm(jdk8)源码分析1-java命令启动流程详解

    JDK8加载源码分析 1.概述 现在大多数互联网公司都是使用java技术体系搭建自己的系统,所以对java开发工程师以及java系统架构师的需求非常的多,虽然普遍的要求都是需要熟悉各种java开发框架 ...

  3. jQuery 源码分析(十八) ready事件详解

    ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...

  4. jQuery 源码分析(十一) 队列模块 Queue详解

    队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...

  5. vuex 源码分析(七) module和namespaced 详解

    当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿. 为了解决这个问题,Vuex允许我们将 store 分割成模块(module).每个模块拥有自己的 state ...

  6. Netty源码分析之Reactor线程模型详解

    上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...

  7. 10.Spark Streaming源码分析:Receiver数据接收全过程详解

    原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/)   在上一篇中介绍了Receiver的整体架构和设计原理,本篇内容主要介绍Receiver在 ...

  8. mybatis 源码分析(三)Executor 详解

    本文将主要介绍 Executor 的整体结构和各子类的功能,并对比效率: 一.Executor 主体结构 1. 类结构 executor 的类结构如图所示: 其各自的功能: BaseExecutor: ...

  9. mybatis 源码分析(八)ResultSetHandler 详解

    本篇博客就是 myabtis 系列的最后一篇了,还剩 ResultSetHandler 没有分析:作为整个 mybatis 最复杂最繁琐的部分,我不打算按步骤一次详解,因为里面的主要内容就是围绕 re ...

  10. mybatis 源码分析(七)KeyGenerator 详解

    一.KeyGenerator 概述 在平时开发的时候经常会有这样的需求,插入数据返回主键,或者插入数据之前需要获取主键,这样的需求在 mybatis 中也是支持的,其中主要的逻辑部分就在 KeyGen ...

随机推荐

  1. spring来了-04-AOP

    概述 aspect object programming 面向切面编程 功能:可以实现“业务代码”与“关注点代码”分离 关注点代码:就是指重复执行的代码 业务代码:核心的业务功能 运行期间,执行核心业 ...

  2. js判断是不是chrome浏览器

    方法一: var isChrome = window.navigator.userAgent.indexOf("Chrome"); <script> var isChr ...

  3. 丢失Ref Edit Control的解决方法

    2010版本excel编制的带有控件的VBA,换在别的电脑使用有可能会出现“找不到工程或库”的错误,在VBE编辑器,打开工具——引用,可以看到“丢失 Ref Edit Control”解决方法是,先把 ...

  4. Qt之QParallelAnimationGroup

    简述 QParallelAnimationGroup类提供动画的并行组. QParallelAnimationGroup - 一个动画容器,当它启动的时候它里面的所有动画也启动,即:并行运行所有动画, ...

  5. WEB前端性能优化:HTML,CSS,JS和服务器端优化

    对前端开发工程师来说,前端性能优化的重要性是不言而喻的,最为大家所知的是YSLOW的23条优化规则,在我的理解中,性能优化不纯粹是指用户访问网站的速度,也包括开发的效率,这里我总结下我理解中的WEB前 ...

  6. Struts2 用 s:if test 判断String类型的对象属性值和单字符是否相等的问题

    Struts2 用 s:if test 判断String类型的对象属性值和单字符是否相等的问题   首先,这里所指的单字符形如:Y,男. 有两种做法: a. <s:if test='news.s ...

  7. Sumblime Text2安装Package Control两种方法+安装插件+注册码

    刚开始不认识sumblime的时候,就直接在网上下载了一个最新版的sumblime text3,只是在配合使用go语言时,出现了一些不为自己知道的奇葩问题,于是果断把3卸载了,改成了sumblime ...

  8. discuzx3.1中引用 Jquery报错的解决办法

    我们可以引用jQuery给JQ赋予一个变量var jq = jQuery.noConflict(); 修改成为:<script type="text/javascript"& ...

  9. 基于TCP协议的网络通信

    TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信.Java对基于TC ...

  10. [示例]NSDictionary编程题-字典的排序应用(iOS6班)

    代码: #import <Foundation/Foundation.h> static NSString * const kName = @"name"; stati ...