一:起因

(1)STL中关于二分查找的函数有三个:lower_bound 、upper_bound 、binary_search  —— 这三个函数都运用于有序区间(当然这也是运用二分查找的前提),以下记录一下这两个函数;

(2)ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置

(3)ForwardIter upper_bound(ForwardIter first, ForwardIter last, const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于值val的位置

二:lower_bound和upper_bound例如以下图所看到的:

(1)lower_bound函数源码:

//这个算法中,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;
}

分析:既然lower_bound()函数返回的是first的指针,那就看first指针变化的位置——first = middle + 1;的条件是 严格的小于(<),即大于等于(>=)时first的位置是不变的。或者能够这样理解,当middle指向的值 < key时,first 指向middle的下一个位置,而下一个位置可能等于或者大于key;因此 该函数是返回一个非递减序列[first,
last)中的第一个大于等于值val的位置。



(2)upper_bound函数源码:

int upper_bound(int *array, int size, int key)
{
int 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;
}

分析:既然upper_bound()函数返回的是first的指针,那就看first指针变化的位置——first = middle + 1;的条件是 小于等于(<=),即仅仅有严格大于(>)时first的位置是不变的。或者能够这样理解,当middle指向的值 <= key时,first 指向middle的下一个位置,而下一个位置可能等于或者大于key,可是要是仍是等于的话,first会继续指向middle的下一位置,直到大于为止;因此
该函数是返回一个非递减序列[first, last)中的第一个大于值val的位置。

(3)binary_search函数源码

//int BinSearch(SeqList*R,int n,KeyType K)
int bin_search(int arr[],const int &n,const int &k)
{
//在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1
int low=0,high=n-1,mid;//置当前查找区间上、下界的初值
while(low<=high)
{
mid=low+((high-low)/2);
//使用(low+high)/2会有整数溢出的问题
//(问题会出如今当low+high的结果大于表达式结果类型所能表示的最大值时,
//这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题
if(arr[mid] == k)
return mid;//查找成功返回
if(arr[mid] > k)
high=mid-1;//继续在R[low..mid-1]中查找
else
low=mid+1;//继续在R[mid+1..high]中查找
}
if(low>high)
return low;//当low>high时表示所查找区间内没有结果,查找失败
} int bin_search2(int arr[],const int &n,const int &k)
{
if(arr && n>0)// 对数组和数组长度进行了推断,很好的改进,上面也应该由此个改进的
{
int low,mid,high;
float rate;
low = 0;
high = n-1;
while(low<=high)
{
rate = (k-arr[low])*1.0/(arr[high]-arr[low]);
if(rate>1 || rate <0)// 相应数组的边界,不在数组中
return -1;
mid = low+(high-low)*rate;
if(arr[mid] == k)
return mid;
else if(arr[mid] > k)
high = mid - 1;
else
low = mid + 1;
}
return -1;// 查找失败
}
return -1;
}

分析:既然binary_search()函数返回的是middle 或 未找到时的指针,那就看middle指针变化的位置——mid = low + (high - low)/2;的条件是最外层while的条件(没有条件限制)第一次相等时就返回middle或者查找失败;因此
该函数是返回一个非递减序列[first, last)中的第一次找到的等于值val的位置,有可能是第一个中间的最后一个(如有序序列 ……3 3 3 ……)。

三:比較说明

(1)分析:既然lower_bound()函数返回的是first的指针,那就看first指针变化的位置——first = middle + 1;的条件是 严格的小于(<),即大于等于(>=)时first的位置是不变的。或者能够这样理解,当middle指向的值 < key时,first 指向middle的下一个位置,而下一个位置可能等于或者大于key;因此 该函数是返回一个非递减序列[first,
last)中的第一个大于等于值val的位置。

(2)分析:既然upper_bound()函数返回的是first的指针,那就看first指针变化的位置——first
= middle + 1;的条件是 小于等于(<=),即仅仅有严格大于(>)时first的位置是不变的。或者能够这样理解,当middle指向的值 <= key时,first 指向middle的下一个位置,而下一个位置可能等于或者大于key,可是要是仍是等于的话,first会继续指向middle的下一位置,直到大于为止;因此 该函数是返回一个非递减序列[first, last)中的第一个大于值val的位置。

(3)分析:既然binary_search()函数返回的是middle
或 未找到时的指针,那就看middle指针变化的位置——mid = low + (high - low)/2;的条件是最外层while的条件(没有条件限制)第一次相等时就返回middle,或者查找失败;因此 该函数是返回一个非递减序列[first, last)中的第一次找到的等于值val的位置,有可能是第一个中间的最后一个(如有序序列
……3 3 3 ……)。

(4)更正说明(优化说明)形式统一,格式统一,这样比較好的,就是不要太脱离你比較熟悉的binary_search()函数的形式,或者核心思想

#include <iostream>

using namespace std;
//这个算法中,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;
}
int upper_bound(int *array, int size, int key)
{
int first = 0;
int 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;
}
int lower(int *,int,int);
int upper(int*,int,int);
int main()
{
int key;
cout << "Hello world!" << endl;
int arr[] = {1,2,2,3,4,4,4,4,5,6,7,9,9,10};
while(cin >> key)
{
cout << "1ziji: " << lower(arr,sizeof(arr)/sizeof(arr[0]),key) << endl;
cout << "2: " << lower_bound(arr,sizeof(arr)/sizeof(arr[0]),key) << endl;
cout << "3: " << upper_bound(arr,sizeof(arr)/sizeof(arr[0]),key) << endl;
cout << "4ziji: " << upper_bound(arr,sizeof(arr)/sizeof(arr[0]),key) << endl;
}
return 0;
}
int lower(int arr[],int size,int key)
{
if(arr && size > 0)
{
int l = 0;
int r = size -1;
int mid;
while(l < r)
{
mid = l + (r-l)/2;
if(*(arr+mid)>=key)
r = mid;
else
l = mid + 1;
}
return l;
}
return -1;
} int upper(int*arr,int size,int key)
{
if(arr && size > 0)
{
int l = 0;
int r = size -1;
int mid;
while(l < r)
{
mid = l + (r-l)/2;
if(arr[mid]>key)
r = mid;
else
l = mid+1;
}
return l;
}
return -1;
}

(5)执行结果(当时没有upper()函数的)

加上upper()函数之后的效果例如以下:



STL 二分查找三兄弟(lower_bound(),upper_bound(),binary_search())的更多相关文章

  1. STL入门--sort,lower_bound,upper_bound,binary_search及常见错误

    首先,先定义数组 int a[10]; 这是今天的主角. 这四个函数都是在数组上操作的 注意要包含头文件 #include<algorithm> sort: sort(a,a+10) 对十 ...

  2. STL中的二分查找———lower_bound,upper_bound,binary_search

    关于STL中的排序和检索,排序一般用sort函数即可,今天来整理一下检索中常用的函数——lower_bound , upper_bound 和 binary_search . STL中关于二分查找的函 ...

  3. STL二分查找函数的应用

    应用二分查找的条件必须是数组有序! 其中二分查找函数有三个binary_serch,upper_bound,lower_bound 测试数组 int n1[]={1,2,2,3,3,4,5}; int ...

  4. C++ STL 二分查找

    转载自 https://www.cnblogs.com/Tang-tangt/p/9291018.html 二分查找的函数有 3 个: 参考:C++ lower_bound 和upper_bound ...

  5. stl lower_bound upper_bound binary_search equal_range

    自己按照stl实现了一个:   http://www.cplusplus.com/reference/algorithm/binary_search/ 这里有个注释,如何判断两个元素相同: Two e ...

  6. STL 二分查找

    实现源码:https://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 1.在一个递增的数组(或vector)中查找元素属于[ s , ...

  7. SDUT2157——Greatest Number(STL二分查找)

    Greatest Number 题目描述Saya likes math, because she think math can make her cleverer.One day, Kudo invi ...

  8. C++ STL之查找算法

    C++STL有好几种查找算法,但是他们的用法上有很多共同的地方: 1.除了binary_search的返回值是bool之外(查找的了返回true,否则返回false),其他所有的查找算法返回值都是一个 ...

  9. lower_bound && upper_bound

     用lower_bound进行二分查找 ●在从小到大排好序的基本类型数组上进行二分查找. 这是二分查找的一种版本,试图在已排序的[first,last)中寻找元素value.如果[first,last ...

随机推荐

  1. Vmware虚拟机下三种网络模式配置

    VMware虚拟机有三种网络模式,分别是Bridged(桥接模式).NAT(网络地址转换模式).Host-only(主机模式). VMware workstation安装好之后会多出两个网络连接,分别 ...

  2. 简单字符串处理 hdu2532 Engine

    本来可以把这篇文章放入上一篇文章里,不过做这个题花了一点时间,也有一点收获,同时觉得网上的这个题目可供参考的文章有些少,那么就单独成篇吧. 首先分析下题目思路: 这个题目是个模拟题,步骤也很清晰. 首 ...

  3. 关于页ASP.NET面布局

    关于页面布局,充分利用Table和分层   从接触ASP.NET到现在已经有一段时间了,起初总是嫌麻烦,想找捷径,凡是想当然,结果导致自己反而走了不少的弯路. 起初刚开始接触ASP.NET的时候,发现 ...

  4. Linux fstab 参数详解

    [root@qs-wg-db1 /]# cat /etc/fstab LABEL=/          /                       ext3    defaults         ...

  5. 利用xshell密钥管理服务器远程登录+VIM dd命令操作之伤之再伤

    1.打开Xshell界面,中文界面方便操作,菜单栏:工具——新建用户密钥生成向导 2.密钥类型选择RSA,密钥长度选择2048位,单击下一步继续: 3.很快生成公钥对,单击下一步继续: 4.密钥名称可 ...

  6. GExpert 1.38 实验版含经典代码格式工具 Berlin 编译版

    安装方法:修改install.reg,然后导入.源代码地址:http://blog.dummzeuch.de/experimental-gexperts-version/ http://bbs.2cc ...

  7. XSS学习笔记(四)-漏洞利用全过程

    <script type="text/javascript" reload="1">setTimeout("window.location ...

  8. Swift - iOS中各种视图控制器(View Controller)的介绍

    在iOS中,不同的视图控制器负责不同的功能,采用不同的风格向用户呈现信息.下面对各个视图控制器做个总结: 1,标准视图控制器 - View Controller 这个控制器只是用来呈现内容.通常会用来 ...

  9. C#面向对象1 类 以及 类的继承(new、ovverride)

    类 的典型代码============================== 包括 属性及其判断赋值  方法  构造函数及其重载 )                 {                  ...

  10. c:foreach如何嵌套循环,求指教,求优化

    java类: public class PopedomItem { private String id; private String pid; private String name; privat ...