众所周知,c++的STL中提供了三个二分查找函数,binary_search(),lower_bound(),upper_bound(),功能分别是找某值是否在数组中出现,找到数组中第一个大于等于某值的元素,找到数组中第一个大于某值的元素。

这三个函数使用十分灵活,可以通过自定义结构体,比较函数,重载大于小于号来实现各种用法,但是它们有一个共同的局限性,就是必须在数组上使用,而不能在整数上使用。

比如我要二分找一个数的向下取整的平方根,范围1e9,肯定不行,1e9的数组都开不了。

大佬的解决方法当然是手写二分辣,但是整数二分是以条件众多,难记难写著称的。所以今天开了一下脑洞,利用野指针实现整数二分。

首先我们观察lower_bound()和upper_bound()调用比较函数时的行为。

struct Example{
int index;
int num;
}exm[];
bool cmp(const Example &x,const Example &y){
printf("%d %d\n",x.index,y.index);
return x.num<y.num;
}
int main(){
for(int i=;i<=;i++){
exm[i].index=i;
exm[i].num=i;
}
Example t;
t.index=-;t.num=;
lower_bound(exm+,exm+,t,cmp);
upper_bound(exm+,exm+,t,cmp);
}
//51 -1
//26 -1
//39 -1
//45 -1
//48 -1
//50 -1
//49 -1
//-1 51
//-1 26
//-1 39
//-1 45
//-1 48
//-1 50

看出来了吧,lower_bound()在调用比较函数时,把数组元素传给比较函数的第一个参数,把待查找元素传给第二个参数

upper_bound()则相反。

自定义的比较函数对于这两个二分查找函数而言是个黑箱,只被关心返回值是几。

那么我们可以让比较函数只关心两个参数的地址,用这个地址瞎搞,不去真的访问这两个地址里面的值,比如刚才给出的例子,找平方根,可以这样写:

const int *p=;
bool cmp(const int &x,const int &y){
return (&x-p)<(&y-p)*(&y-p);
}
int main(){
int k;
scanf("%d",&k);
printf("%d",upper_bound(p+,p+k+,p[k],cmp)--p);
}
//91749281
//9578
//注意溢出

此方法的局限性:

1,指针长度有限制且无法自己定义。

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
printf("the size of int* is %d\n",sizeof(int*));
printf("the size of long long is %d\n",sizeof(long long));
}
//the size of int* is 8
//the size of long long is 8

但是这个貌似没太大问题,因为所有指针,不管它指向什么,都是8位的,和long long一样长,足够了。

2,只能用于正数

指针运算没有负数,对于此种情况只能用设虚拟零点的方法解决。

3,存在非法访问的风险

目前笔者未找到任何证据能够证明二分查找函数本身不去访问指针指向的内容,有可能导致未知的非法访问。

奇思妙想:利用野指针和lower_bound()/upper_bound()函数实现整数二分的更多相关文章

  1. 李洪强iOS开发之【Objective-C】09-空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储任何内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0. 下面两个都是空指针 ...

  2. 【Objective-C】4-空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储任何内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0. 下面两个都是空指针 ...

  3. Objective-C 空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储任何内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0. 下面两个都是空指针 ...

  4. 【Objective-C】09-空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储不论什么内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针.在没有被详细初始化之前.其值为0. 以下两个都是空 ...

  5. 【Objective-C】-空指针和野指针

    一.什么是空指针和野指针 1.空指针 1> 没有存储任何内存地址的指针就称为空指针(NULL指针) 2> 空指针就是被赋值为0的指针,在没有被具体初始化之前,其值为0. 下面两个都是空指针 ...

  6. C++中lower_bound函数和upper_bound函数

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

  7. C语言之free函数及野指针

    [FROM MSDN && 百科] 原型:  void free(void *ptr); #include<stdlib.h>或#include <malloc.h& ...

  8. STL之std::set、std::map的lower_bound和upper_bound函数使用说明

    由于在使用std::map时感觉lower_bound和upper_bound函数了解不多,这里整理并记录下相关用法及功能. STL的map.multimap.set.multiset都有三个比较特殊 ...

  9. lower_bound和upper_bound函数

    lower_bound(ForwardIter first,ForwardIter last,const_TP & val) upper_bound(ForwardIter first,For ...

随机推荐

  1. Go基础之基本数据类型

    Go基础之基本数据类型 基本数据类型 整形 int8.int16.int32.int64 无符号整形:uint8.uint16.uint32.uint64 uint8就是我们熟知的byte型 类型 描 ...

  2. Vue2.0源码思维导图-------------Vue 初始化

    上一节看完<Vue源码思维导图-------------Vue 构造函数.原型.静态属性和方法>,这节将会以new Vue()为入口,大体看下 this._init()要做的事情. fun ...

  3. flutter 卡在Running Gradle task 'assembleDebug'...

    Android项目运行时出错 卡在Initializing gradle… 运行时会卡在Initializing gradle..., 此时因为Android项目会用到Gradle, 如果没有FQ,下 ...

  4. TeleportArea可瞬移的目标位置

    TeleportArea.png 1.可以自定义mesh ,想要什么区域就可以设置什么区域的mesh网格.2.Collider 组件必须有,否则无法进行位置移动,它用来检测激光笔是否打到该区域.3.M ...

  5. tornado的安装

      centos6.4 安装tornado框架连接工具  xshell 工具 1.如果在windows下有tornado的安装包首先现在上装到linux下的上传工具:yum install lrzsz ...

  6. Go语言基础:make,new, len, cap, append, delete方法

      前面提到不少Go的内建函数,这篇文章学习下如何使用.. make 先拿 make 开刀,可是一开始我就进入了误区,因为我想先找到他的源码,先是发现 src/builtin/builtin.go 中 ...

  7. python 获取手机设备号

    上代码 ##获取设备多台设备号列表 def get_deviceid(): str_init=' ' all_info= os.popen('adb devices').readlines() pri ...

  8. Linux Kernel Development有关内存管理

    1 Pages Page的概念来源为处理器Processor的部件MMU(Memory Management Unit),MMU通过设置好的页表(通过设置CR3寄存器,指向页目录所在的物理内存)对内存 ...

  9. 《深入理解Java虚拟机》-(实战)boolean类型在虚拟机中是如何处理的

    这里先引出Java的8大基本类型.直接上图吧. 可以看到,除了boolean和char类型之外,越往下的类型的值域是包含以上的值域的.因此,从上面的基本类型转换成下面的基本类型,无需强制转换.关于它们 ...

  10. selenium 滑动页面至元素可见

    滚动页面 在自动化操作中,如果web页面过长,而我们需要的元素并不在当前可视页面中,那么selenium就无法对其进行操作:此时,我们就需要像平时操作浏览器一样来滚动页面,使我们需要操作的对象可见! ...