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;
}
时间: 2024-08-06 01:06:34

STL源码学习----lower_bound和upper_bound算法的相关文章

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

http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html PS: lower_bound of value 就是最后一个 < value 或者第一个 = value的位置 upper_bound of value 就是第一个 > value的位置 lower_bound的意思是一段相等的序列的头(闭)和尾(开)的位置 STL中关于二分查找的函数有三个lower_bound .upper_bound .binary_search

【STL源码学习】STL算法学习之二

第一章:前言 学习笔记,记录学习STL算法的一些个人所得,在以后想用的时候可以快速拾起. 第二章:明细 copy 函数原型: template <class InputIterator, class OutputIterator> OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result); 函数作用: 将[first,last)区间的元素拷贝至result开头的迭代器区间,并返回赋值

【STL源码学习】std::list类的类型别名分析

有了点模板元编程的traits基础,看STL源码清晰多了,以前看源码的时候总被各种各样的typedef给折腾得看不下去, 将<list>头文件的类继承结构简化如下 #include <xmemory> #include <stdexcept> #define _STD_BEGIN namespace std { #define _STD_END } _STD_BEGIN // 第一个模板参数 template <class _Val_types> class

C++ STL源码学习之算法篇

///由于篇幅太长,因此,删去了很多接口,只分析了内部实现,算法对迭代器的要求也被删去 /// search. template <class _ForwardIter1, class _ForwardIter2> _ForwardIter1 search(_ForwardIter1 __first1, _ForwardIter1 __last1, _ForwardIter2 __first2, _ForwardIter2 __last2) { /// Test for empty range

【STL源码学习】细品vector

第一节:vector简介 vector是一种典型的类模板,使用的时候必须进行实例化. vector的数据存储在数组上,支持随机访问迭代器,支持下标操作[]和at操作,支持手动扩容和自动容量增长. vector是STL中的最常用容器,并支持STL的通用算法. 第二节:vector的迭代器介绍 vector支持iterator.const_iterator.reverse_iterator.const_reverse_iterator,前两个是正向迭代器,后两个是逆向迭代器. 迭代器支持操作:*操作

C++ STL源码学习(之RB Tree篇)

stl_tree.h 这是整个STL中最复杂的数据结构,也是我接触到的最复杂的数据结构之一 /** Red-black tree class, designed for use in implementing STL associative containers (set, multiset, map, and multimap). The insertion and deletion algorithms are based on those in Cormen, Leiserson, and

【STL源码学习】STL算法学习之三

第一章:前言 数量不多,用到的时候会很爽. 第二章:明细 STL算法中的又一个分类:分割:将已有元素按照既定规则分割成两部分.  is_partitioned 函数原型: template <class InputIterator, class UnaryPredicate> bool is_partitioned (InputIterator first, InputIterator last, UnaryPredicate pred); 函数作用: 如果序列被分为两部分,前一部分pred都

【STL源码学习】STL算法学习之一

第一章:引子 STL包含的算法头文件有三个:<algorithm><numeric><functional>,其中最大最常用的是<algorithm>,今天学习的是<algorithm>包含的算法中的第一部分:非修改顺序操作算法. 接下来学习的算法基于C++11标准,较老的IDE会支持不全面或者部分算法不支持. 第二章:原型解析 如分类名称体现的信息,本节的所有函数都不会修改序列,并且原理上都是顺序遍历迭代器实现的. all_of 函数原型: t

【STL源码学习】STL算法学习之四

排序算法是STL算法中相当常用的一个类别,包括部分排序和全部排序算法,依据效率和应用场景进行选择. 明细: sort 函数原型: template <class RandomAccessIterator> void sort (RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void sort (RandomAcc