一:起因

(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. C#数组集合使用 排序的问题

    //没有顺序 //ArrayList a = new ArrayList(); //a.Add("asda"); //a.Add("asda222222"); ...

  2. RelativeLayout的一些感想

    1.如果只是是3-4个线性,则可以考虑RelativeLayout;多于等于5个还是尽量考虑LinearLayout好 补充:如果要把RelativeLayout作为线性布局的话,可以采用不断设置be ...

  3. SecureCRT辅助解决方案

    SecureCRT辅助解决方案 1. 下载SecureCRT 7.3版本并激活: 2. SecureCRT linux配色方案: 3. SecureCRT设置log保存方案: 1. secureCRT ...

  4. tomcat启动后ids页面无法访问

    修改servers-->tomcat6.0-->server.xml <Context docBase="/tds7030-web" path="&qu ...

  5. 【转】windows 7系统安装与配置Tomcat服务器环境

    原文链接: windows 7系统安装与配置Tomcat服务器环境 工具/原料 jdk-8u51-windows-x64(我的系统是64位系统,32位的请选x86下载)下载地址:http://www. ...

  6. VS2008 Project : error PRJ0019: 某个工具从以下位置返回了错误代码: "正在执行生成后事件..."解决方案

    右键工程属性 -> 配置属性 -> 生成事件 ->生成后事件,命令行中的路径加上双引号,如 copy $(ProjectDir)\export\win32\Debug\$(Proje ...

  7. BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )

    水状压dp. dp(x, s) = max{ dp( x - 1, s - {h} ) } + 奖励(假如拿到的) (h∈s). 时间复杂度O(n * 2^n) ------------------- ...

  8. 它们偷偷干了啥?教你监督APP的运行

    由于Android系统的开放性,很多APP都会在后台运行各种我们不知道的权限,不仅泄露我们隐私,也给系统本身带来极大安全隐患.而且现在很普遍的是,在安装APP时它总会索取特别多的权限,又是拍照又是地理 ...

  9. Ember.js - About

    Ember.js - About More Productive Out of the Box.   Write dramatically less code with Ember's Handleb ...

  10. CSS三角形制作样式

    .triangle{ display: block; height: 0; position: absolute; width: 0; border: 9px solid; border-color: ...