二分查找很简单,原理就不说了。STL中关于二分查找的函数有三个lower_bound 、upper_bound 、binary_search 。这三个函数都运用于有序区间(当然这也是运用二分查找的前提)。

其中如果寻找的value存在,那么lower_bound返回一个迭代器指向其中第一个这个元素。upper_bound返回一个迭代器指向其中最后一个这个元素的下一个位置(明确点说就是返回在不破坏顺序的情况下,可插入value的最后一个位置)。如果寻找的value不存在,那么lower_bound和upper_bound都返回“假设这样的元素存在时应该出现的位置”。要指出的是lower_bound和upper_bound在源码中只是变换了if—else语句判定条件的顺序,就产生了最终迭代器位置不同的效果。

binary_search试图在已排序的[first,last)中寻找元素value,若存在就返回true,若不存在则返回false。返回单纯的布尔值也许不能满足需求,而lower_bound、upper_bound能提供额外的信息。事实上由源码可知binary_search便是利用lower_bound求出元素应该出现的位置,然后再比较该位置   的值与value的值。该函数有两个版本一个是operator< ,另外一个是利用仿函数comp进行比较。

具体分析见源码

//这是forward版本
template <class ForwardIterator, class T>
inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
                                   const T& value) {
  return __lower_bound(first, last, value, distance_type(first),
                       iterator_category(first));
}
 
// 这是版本一的 forward_iterator 版本
template <class ForwardIterator, class T, class Distance>
ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last,
                              const T& value, Distance*,
                              forward_iterator_tag) {
  Distance len = 0;
  distance(first, last, len);    // 求取整个范围的长度,ForwardIterator没有-n操作
  Distance half;
  ForwardIterator middle;
 
  while (len > 0) {                        //为了跳出循环,而定义了len,如果用while(true) 然后每次判定长度在break,也行,不过没这个好
    half = len >> 1;            // 除以2,注意这种移位写法,不需编译器进行优化
    middle = first;                 // 这两行令middle 指向中间位置
    advance(middle, half);       //ForwardIterator没有+n的操作
    if (*middle < value) {        // 如果中间位置的元素值 < 标的值,value在后半区间
      first = middle;            // 这两行令 first 指向 middle 的下一位置
      ++first;
      len = len - half - 1;        // 修正 len,回头测试循环条件
    }
else                        // 注意如果是相等的话,那么执行的是else语句,在前半部分找
                            // 与opper_bound进行比较
      len = half;                // 修正 len,回头测试循环条件
  }
  return first;
}
// 这是带comp反函数的 forward_iterator 版本
template <class ForwardIterator, class T, class Compare, class Distance>
ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last,
                              const T& value, Compare comp, Distance*,
                              forward_iterator_tag) {
  Distance len = 0;
  distance(first, last, len);
  Distance half;
  ForwardIterator middle;
 
  while (len > 0) {
    half = len >> 1;
    middle = first;
    advance(middle, half);
    if (comp(*middle, value)) {
      first = middle;
      ++first;
      len = len - half - 1;
    }
    else
      len = half;
  }
  return first;
}
 
// 这是random_access_iterator版本
template <class ForwardIterator, class T, class Compare>
inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last,
                                   const T& value, Compare comp) {
  return __lower_bound(first, last, value, comp, distance_type(first),
                       iterator_category(first));
}
 
// 这是版本一的 random_access_iterator 版本
template <class RandomAccessIterator, class T, class Distance>
RandomAccessIterator __lower_bound(RandomAccessIterator first,
                                   RandomAccessIterator last, const T& value,
                                   Distance*, random_access_iterator_tag) {
  Distance len = last - first;    //求取整个范围的长度,与ForwarIterator版本进行比较
  Distance half;
  RandomAccessIterator middle;
 
  while (len > 0) {
half = len >> 1;            
middle = first + half;        
    if (*middle < value) {        
      first = middle + 1;        
      len = len - half - 1;        //修正 len,回头测试循环条件,RamdonAccessIterator版本
    }
    else
      len = half;                
  }
  return first;
}
 
 
 
//这是带comp仿函数 random_access_iterator 版本
template <class RandomAccessIterator, class T, class Compare, class Distance>
RandomAccessIterator __lower_bound(RandomAccessIterator first,
                                   RandomAccessIterator last,
                                   const T& value, Compare comp, Distance*,
                                   random_access_iterator_tag) {
  Distance len = last - first;
  Distance half;
  RandomAccessIterator middle;
 
  while (len > 0) {
    half = len >> 1;
    middle = first + half;
    if (comp(*middle, value)) {
      first = middle + 1;
      len = len - half - 1;
    }
    else
      len = half;
  }
  return first;
}
 
// 这是forward_iterator版本
template <class ForwardIterator, class T>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
                                   const T& value) {
  return __upper_bound(first, last, value, distance_type(first),
                       iterator_category(first));
}
 
// 这是版本一的 forward_iterator 版本
template <class ForwardIterator, class T, class Distance>
ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last,
                              const T& value, Distance*,
                              forward_iterator_tag) {
  Distance len = 0;
  distance(first, last, len);    
  Distance half;
  ForwardIterator middle;
 
  while (len > 0) {
    half = len >> 1;            
    middle = first;                
    advance(middle, half);
    if (value < *middle)        // 如果中间位置的元素值大于标的值,证明在前半部分
      len = half;                // 修正len
else {                        // 注意如果元素值相等的话,那么是在后半部分找
                            // 与lower_bound进行比较
      first = middle;            // 在下半部分,令first指向middle的下一个位置
      ++first;
      len = len - half - 1;        // 修正 len
    }
  }
  return first;
}
 
// 这是版本一的 random_access_iterator 版本
template <class RandomAccessIterator, class T, class Distance>
RandomAccessIterator __upper_bound(RandomAccessIterator first,
                                   RandomAccessIterator last, const T& value,
                                   Distance*, random_access_iterator_tag) {
  Distance len = last - first;    
  Distance half;
  RandomAccessIterator middle;
 
  while (len > 0) {
    half = len >> 1;            
    middle = first + half;        
    if (value < *middle)        
      len = half;                    
     else {
      first = middle + 1;        
      len = len - half - 1;        
    }
  }
  return first;
}
 
// 这是带comp的版本
template <class ForwardIterator, class T, class Compare>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last,
                                   const T& value, Compare comp) {
  return __upper_bound(first, last, value, comp, distance_type(first),
                       iterator_category(first));
}
 
// 这是带comp的 forward_iterator 版本
template <class ForwardIterator, class T, class Compare, class Distance>
ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last,
                              const T& value, Compare comp, Distance*,
                              forward_iterator_tag) {
  Distance len = 0;
  distance(first, last, len);
  Distance half;
  ForwardIterator middle;
 
  while (len > 0) {
    half = len >> 1;
    middle = first;
    advance(middle, half);
    if (comp(value, *middle))
      len = half;
    else {
      first = middle;
      ++first;
      len = len - half - 1;
    }
  }
  return first;
}
 
// 这是带comp的 random_access_iterator 版本
template <class RandomAccessIterator, class T, class Compare, class Distance>
RandomAccessIterator __upper_bound(RandomAccessIterator first,
                                   RandomAccessIterator last,
                                   const T& value, Compare comp, Distance*,
                                   random_access_iterator_tag) {
  Distance len = last - first;
  Distance half;
  RandomAccessIterator middle;
 
  while (len > 0) {
    half = len >> 1;
    middle = first + half;
    if (comp(value, *middle))
      len = half;
    else {
      first = middle + 1;
      len = len - half - 1;
    }
  }
  return first;
}
 
// 版本一
template <class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last,
                   const T& value) {
  ForwardIterator i = lower_bound(first, last, value);  
//这里的实现就是调用的lower_bound ,并且如果元素不存在那么lower_bound指向的元素一定是
//operator < 为ture的地方。
  return i != last && !(value < *i);
}
 
// 版本二
template <class ForwardIterator, class T, class Compare>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value,
                   Compare comp) {
  ForwardIterator i = lower_bound(first, last, value, comp);
  return i != last && !comp(value, *i);
}
--------------------- 
  原文:https://blog.csdn.net/sicofield/article/details/8740141

lower_bound 、upper_bound 、binary_search相关推荐

  1. lower_bound、upper_bound、equal_range详解

    lower_bound.upper_bound.equal_range定义在头文件<algorithm>中 同时,有序容器如set,map也会提供成员函数lower_bound. 函数声明 ...

  2. vector的插入、lower_bound、upper_bound、equal_range实例

    对于这几个函数的一些实例以便于理解: #include <cstdlib> #include <cstdio> #include <cstring> #includ ...

  3. binary_search()、upper_bound()、lower_bound() 二分查找

    vector<int> a = {0,1,2,2,3,4}; 使用前提是a已经是升序排列 cout << binary_search(a.begin(), a.end(), 3 ...

  4. 二分查找、upper_bound、lower_bound

    整理及总结二分查找的判断和边界细节 修改版 package com.leej.binarysearch;import java.util.Arrays;/*** @author jerry* @cre ...

  5. [C++ STL algorithm] lower_bound、upper_bound、unique的本质

    lower_bound:返回第一个大于等于查找值的地址 upper_bound:返回第一个严格大于查找值的地址 使用这两个函数需要的头文件 #include <algorithm> usi ...

  6. C++ Tips:static const size_t nops、string substr、upper_bound、find()

    维基百科连接

  7. 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)...

    一.移除性算法 (remove) C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  8. 从零开始学C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)

    一.移除性算法 (remove) C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  9. 恶补C++:重载手写堆结构体lower_bound()vector构造、析构函数setmappairstack

    部分目录 运算符重载 C++ 函数调用运算符 () 重载 我的经历 关于this 关于友元 附:重载函数 C++补充 优先队列 手写堆 手写堆的存储 手写堆的两个基本操作 插入节点的原理 求当前堆的最 ...

  10. C++/C--二分查找之lower_bound( )和upper_bound( )【转载】

    文章目录 1 头文件及相关函数 2 函数lower_bound() 3 函数upper_bound() 4 示例 1 头文件及相关函数 头文件: #include <algorithm> ...

最新文章

  1. 机器学习模型评估与超参数调优详解
  2. SpringBoot 2.1.3配置log4j2日志框架完整代码示例
  3. ASP.NET Core on K8S深入学习(5)Rolling Update
  4. No grammar constraints (DTD or XML schema).....两种解决方法
  5. activex控件 新对象 ocx 初始化_Office已经支持64位的树控件Treeview了
  6. redux 源码详解
  7. python中main函数在运行中不是必须要写的_Python必备知识之“if __name__ == '__main__':”...
  8. iOS JSPatch 热修复使用
  9. 2018.11.05-4028-撸串(string)
  10. Happy Week
  11. 使用easyos递归删除城通网盘的日志
  12. android sd卡 spi,SD卡总结-SPI模式
  13. 天龙八部,数据可视化分析虚竹和童姥居然关系非同一般
  14. Oracle 11g 找不到文件 D:\app\Administrator\product\11.2.0\dbhome_1\oc4j\j2ee\oc4j_appli
  15. MFC edit control动态设置密码
  16. 国产AI绘画海克斯科技——爱作画AIGC开放平台
  17. 在PHP中全面阻止SQL注入式攻击之三
  18. 【中国大学MOOC】java程序设计-week3-用“埃氏筛法”求2~100以内的素数
  19. centos7安装harbor详细教程
  20. 笔记本电脑计算机无法启动怎么办,联想笔记本开不了机怎么办 电脑开机进不了系统怎么办...

热门文章

  1. 小米盒子显示连不上服务器,小米盒子连不上WiFi?这七个技巧绝对管用
  2. python学习之——假人配对
  3. 数字后端基本概念介绍Wire
  4. 广州行键CRM客户关系管理系统
  5. rpm -ivh安装mysql_rpm的用法 详解
  6. monodepth2训练细节
  7. 【路径规划】基于蚁群求解多旅行商MTSP问题matlab源码
  8. 使用Python比较两个文本文件的相似度
  9. ERP系统成本计算方法大揭秘?
  10. 基于cnn的人脸识别_人脸识别技术:从传统方法到深度学习