stl upper_bound函数实现

2023-05-16

写了一个upper_bound的实现。其中递归使用二分法求解最上界,虽然写的完全不像STL的风格,但是练手还是可以的。

view plaincopy to clipboardprint?
01.#include<iostream>  
02.#include<iterator>  
03.#include<cstring>  
04.#include<cassert>  
05.using namespace std;  
06.int UpperBound(int* a, int start, int end , const int& value){  
07.    int mid = 0;  
08.    int index = 0;  
09.    int up_index = 0;  
10.    if(a[end]<value)  
11. // 特判比最后一个数大时,end+1  
12.        return end+1;  
13.        //这里是经典的二分  
14.    while(start<= end){  
15.        mid = start + (end - start)/2;  
16.        if(a[mid] == value){  
17.            index = mid + 1;  
18.                        // 去递归的找一下上界  
19.            up_index = UpperBound(a,mid+1,end,value);  
20.                        // 如果找到的上界比现在的还小,那么就用现在的  
21.            return up_index > index? up_index : index;  
22.        }  
23.        else if(a[mid]<value){  
24.            start = mid+1;  
25.        }  
26.        else{  
27.            end = mid-1;  
28.                        // 记录上界  
29.            index = mid;  
30.        }  
31.    }  
32.    return index;  
33.} 
#include<iostream>
#include<iterator>
#include<cstring>
#include<cassert>
using namespace std;
int UpperBound(int* a, int start, int end , const int& value){
 int mid = 0;
 int index = 0;
 int up_index = 0;
 if(a[end]<value)
 // 特判比最后一个数大时,end+1
  return end+1;
        //这里是经典的二分
 while(start<= end){
  mid = start + (end - start)/2;
  if(a[mid] == value){
   index = mid + 1;
                        // 去递归的找一下上界
   up_index = UpperBound(a,mid+1,end,value);
                        // 如果找到的上界比现在的还小,那么就用现在的
   return up_index > index? up_index : index;
  }
  else if(a[mid]<value){
   start = mid+1;
  }
  else{
   end = mid-1;
                        // 记录上界
   index = mid;
  }
 }
 return index;
}

如果原数组中没有存在那个元素,就根本没有调用那个递归程序,递归只有在出现多个此元素时才会调用。另外中间递归调用段地方还可以改写为:

view plaincopy to clipboardprint?
01.if(a[mid] == value){  
02.   index = mid + 1;  
03.   /* 
04.    up_index = UpperBound(a,mid+1,end,value); 
05.    return up_index > index? up_index : index; 
06.   */ 
07.   // 因为只有在递归调用中start>end时,才会返回一个index = 0  
08.   return (mid+1>end) ? index : UpperBound(a,mid+1,end,value);  
09.} 
if(a[mid] == value){
   index = mid + 1;
   /*
    up_index = UpperBound(a,mid+1,end,value);
    return up_index > index? up_index : index;
   */
   // 因为只有在递归调用中start>end时,才会返回一个index = 0
   return (mid+1>end) ? index : UpperBound(a,mid+1,end,value);
}

这样写完后写一下测试代码,顺便wrap一层upper_bound:

view plaincopy to clipboardprint?
01.int upper_bound(int * a,int n, const int& value){  
02.    // 使用宏可以在编译时去除  
03.    #ifdef TEST  
04.    // pre-condition  
05.    assert(NULL != a && n>0);  
06.    // check the array a is sorted by elements      
07.    for(int i = 1; i < n; i++){  
08.         assert(a[i-1]<=a[i]);  
09.    }  
10.    int * tmp_a = new int[n];  
11.    memcpy(tmp_a,a,sizeof(int)*n);  
12.    #endif  
13.    int index = UpperBound(a,0,n-1,value);  
14.      
15.    #ifdef TEST  
16.    // post-condition  
17.    //check whether the array is changed or not  
18.    for(int i = 0; i < n; i++)  
19.        assert(a[i] == tmp_a[i]);  
20.    if(index == 0){  
21.        // min  
22.        assert(a[index]>value);  
23.    }  
24.    else if(index == n){  
25.        // max  
26.        assert(a[index-1]<=value);  
27.    }  
28.    else{  
29.        assert(a[index]>value && a[index-1]<=value);  
30.    }  
31.    delete [] tmp_a;  
32.    #endif  
33.    return index;  
34.} 
int upper_bound(int * a,int n, const int& value){
    // 使用宏可以在编译时去除
    #ifdef TEST
    // pre-condition
    assert(NULL != a && n>0);
    // check the array a is sorted by elements   
    for(int i = 1; i < n; i++){
         assert(a[i-1]<=a[i]);
    }
    int * tmp_a = new int[n];
    memcpy(tmp_a,a,sizeof(int)*n);
    #endif
    int index = UpperBound(a,0,n-1,value);
   
    #ifdef TEST
    // post-condition
    //check whether the array is changed or not
    for(int i = 0; i < n; i++)
        assert(a[i] == tmp_a[i]);
    if(index == 0){
        // min
        assert(a[index]>value);
    }
    else if(index == n){
        // max
        assert(a[index-1]<=value);
    }
    else{
        assert(a[index]>value && a[index-1]<=value);
    }
    delete [] tmp_a;
    #endif
    return index;
}

如果希望别人不调用UpperBound而只调用upper_bound,可以使用static 关键字, 将UpperBound限制在只在本文件中使用。别人调用就只能调用upper_bound()函数。不过STL的教学源码比我这精简的多,根本无须使用递归。真正的STL源码变量名称会使用下划线__作为起始。

view plaincopy to clipboardprint?
01.template <class ForwardIterator, class T>  
02.  ForwardIterator upper_bound ( ForwardIterator first, ForwardIterator last, const T& value )  
03.{  
04.  ForwardIterator it;  
05.  iterator_traits<ForwardIterator>::distance_type count, step;  
06.  count = distance(first,last);  
07.  while (count>0)  
08.  {  
09.    it = first; step=count/2; advance (it,step);  
10.    if (!(value<*it))                 // or: if (!comp(value,*it)), for the comp version  
11.      { first=++it; count-=step+1;  }  
12.    else count=step;  
13.  }  
14.  return first;  
15.} 
template <class ForwardIterator, class T>
  ForwardIterator upper_bound ( ForwardIterator first, ForwardIterator last, const T& value )
{
  ForwardIterator it;
  iterator_traits<ForwardIterator>::distance_type count, step;
  count = distance(first,last);
  while (count>0)
  {
    it = first; step=count/2; advance (it,step);
    if (!(value<*it))                 // or: if (!comp(value,*it)), for the comp version
      { first=++it; count-=step+1;  }
    else count=step;
  }
  return first;
}
 

这里的advance()函数定义类似:

view plaincopy to clipboardprint?
01.template<class Iterator, class Distance>  
02.void advance(Iterator& i, Distance n);  
03.类似于  i = x.begin()+n; i is an iterator of x 
template<class Iterator, class Distance>
void advance(Iterator& i, Distance n);
类似于  i = x.begin()+n; i is an iterator of x

最后把主函数贴上做结:

view plaincopy to clipboardprint?
01.int main(int argc, char* argv[])  
02.{  
03. 
04.   // 这里你可以使用random的方法进行测试。  
05. 
06.    int x[] = {1,2,3,4,5,5,5,5,9};  
07.    vector<int> v(x,x+9);  
08.    sort(v.begin(),v.end());  
09.    cout << (int)(upper_bound(v.begin(),v.end(),9)-v.begin());  
10.    cout << upper_bound(x,9,9);  
11.    return 0;  
12.}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stl upper_bound函数实现 的相关文章

随机推荐

  • 数组元素交叉排列的算法题(a1 a2 a3 .. an b1 b2 b3 .. bn -->a 1 b1, a2 b2, a3 b3, .. an bn ) 概论思想(perfect shuffle 算法)

    perfect shuffle 算法 今天又发现一个关于完美洗牌的算法 这个比较简单一些 xff0c 由 microsoft的Peiyush Jain提出 原论文 xff1a A Simple In Place Algorithm for
  • [操作系统]学习操作系统的经典书籍

    http blog chinaunix net u1 43966 showart 396940 html 介绍了一些操作系统学习的经典书籍 xff0c 包括理论上的 具体操作系统的 Abraham Silberschatz的两本书 xff1
  • Spring源码之AbstractApplicationContext解析(refresh)

    Spring源码之AbstractApplicationContext解析 阅读前提须知 1 此源码是在我公司的随便一个Spring boot项目中查看的 xff0c 具体方法就是双击shift xff0c 搜索AbstractApplic
  • 岁月清浅,邀你入梦

    这世间本应美好 xff0c 怎无奈痛苦缠身 xff0c 卿心亦真 xff0c 免世人之苦 xff0c 乐自身之本 卿之容 xff0c 多沉醉 xff0c 于心赞 xff0c 日夜思 淡若微风的陪伴 xff0c 奈何情深缘浅 只相识 xff0
  • sqli-labs环境搭建

    sqli labs环境搭建 链接 xff1a https www fujieace com penetration test sqli labs ec html
  • python打印等腰三角形

    d 61 int input 39 enter an int 39 l 61 39 39 2 d 1 d 初始化列表 for i in range d l i 61 list l i 字符串转列表 x 61 i y 61 0 x 61 d
  • 实战|如何消除又臭又长的if...else判断更优雅的编程?

    最近在做代码重构 xff0c 发现了很多代码的烂味道 其他的不多说 xff0c 今天主要说说那些又臭又长的if else要如何重构 在介绍更更优雅的编程之前 xff0c 让我们一起回顾一下 xff0c 不好的if else代码 一 又臭又长
  • 最新版Ubuntu 17.10与Windows双系统安装、配置与美化教程(转载)

    感谢原创 xff0c 原文地址 http www jianshu com p 62d947731401 TOC 本教程基于Ubuntu 17 10 xff0c 但是除了下面的Gnome插件部分 xff0c 同时也支持Ubuntu16以上的几
  • Win8.1系统下VirtualBox的各种网络配置方法——Bridged networking

    概述配置仅界面设置桥接到无线网络接口与桥接到有线网络接口的网络相比不同操作系统下桥接网络的缺点 概述 VirtualBox使用主机系统上的一个设备驱动器 用于过滤物理网络适配器的数据 xff0c 因此也被称为网络过滤驱动器 net filt
  • 设置电脑网络唤醒-华硕主板+向日葵

    我一直用向日葵的开机棒唤醒电脑 xff0c 后来重装系统 xff0c 就开机棒失效了 由于是重装系统 xff0c 所以BIOS的设置没问题的 xff0c 就怀疑是新系统需要设置 xff0c 找了好久找到这个教程 xff0c 记录一下 参考这
  • 各种排序的运行时间对比

    冒泡排序 cpp view plain copy time 34 220s include lt cstring gt include lt iostream gt include lt fstream gt include lt algo
  • Cordova概述

    Cordova Apache Cordova is an open source mobile development framework It allows you to use standard web technologies HTM
  • Ubuntu18.04 项目配置

    有问题多重启就好啦 1 换源2 配置输入法3 安装Nvidia驱动4 安装Cuda5 下载谷歌浏览器并安装6 安装Anaconda37 pip换源8 Ubuntu18 04 无法通过蓝牙链接 Airpods9 安装PyCharm10 安装P
  • 基于numpy的CNN实现,进行MNIST手写数字识别

    主要框架来自于这篇文章 xff1a https blog csdn net qq 36393962 article details 99354969 xff0c 下面会以原文来代称这篇文章 本文在原文的基础上增加了交叉熵以及mnist数据集
  • libevent 的http模块实现http服务器

    首先声明 xff0c libevent的http模块是为单线程设计的 xff0c 如果业务逻辑中有耗时操作 xff0c 则需要自行设计线程池以便提高吞吐量 xff0c 每个工作线程中都要运行一个event base loop和一个evhtt
  • swig 使用案例

    包含数组 结构体嵌套 xff0c 函数指针传递等基本操作 swig默认不支持数组元素的写入 xff0c 如果想操作数组元素 xff0c 可以附加一些接口函数实现 比如下面在处理结构体的数组成员时 xff0c 使用 extend命令扩展了对应
  • 攻击防御实例——SQL注入

    攻击防御实例 SQL注入 1 i 表示匹配的时候不区分大小写 2 s 匹配任何不可见字符 xff0c 包括空格 制表符 换页符等等 等价于 f n r t v 3 information schema xff1a 是一个数据库 xff0c
  • 264 nal type

    NUAL HEAD 43 43 0 1 2 3 4 5 6 7 43 43 43 43 43 43 43 43 43 F NRI Type 43 43 F xff1d Forbidden zero bit 61 0 NRI 61 Nal r
  • SubClassWindow详解

    许多Windows程序员都是跳过SDK直接进行RAD开发工具 或VC xff0c 我想VC应不属于RAD 的学习 xff0c 有些人可能对子类化机制比较陌生 我们先看看什么是Windows的子类化 Windows给我们或是说给它自己定义了许
  • stl upper_bound函数实现

    写了一个upper bound的实现 其中递归使用二分法求解最上界 xff0c 虽然写的完全不像STL的风格 xff0c 但是练手还是可以的 view plaincopy to clipboardprint 01 include lt io