C++ STL中的二分法
二分法介绍
狭义的二分法是一种在有序的数组中查找是否存在某个值的算法。广义的二分法不一定需要显式的数组,只需要有序的解空间即可。(此处解空间借用线性代数的称谓,仅表示所有合法解的集合,与线性代数无关)
有序解空间:设[a,b]是问题P的解空间(解必须是整数,a,b也是整数),解空间有序等价于若x是问题P的合法解,则任意c小于(大于)x一定是问题P的合法解。
不严谨地说,由于单调有界可知存在一个分界点,一侧是合法解,另一侧是不合法解(根据问题需要,单独定义分界点是否合法)。
最流行的二分法是使用两个指针left和right。该方法适合用于查找是否存在某个值(狭义),但对于找分界点的问题(广义),该方法最后必然会得到left=right+1的结果,这时难以弄清楚left和right谁是真正的分界点。
查询了C++ STL代码发现,STL没有使用这种方法。在STL中,使用一个指针first,指向当前最小的未判断元素,一个count计数器,表示当前未判断元素个数。
C++ STL中的代码
Algorithm头文件中的std::lower_bound()可以在有序解空间中查找大于val的最小数下标。
std::lower_bound()代码如下:
template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = distance(first,last);
while (count>0)
{
it = first; step=count/2; advance (it,step);
if (*it<val) { // or: if (comp(*it,val)), for version (2)
first=++it;
count-=step+1;
}
else count=step;
}
return first;
}
该方法需要显式的解空间作为参数,实际情况下并非所有解空间都能被显式存储,有时只知道一个函数f(),f(index)表示解空间的第index个值。在这种情况下,需要自己直接实现std::lower_bound()的功能。
代码分析
不妨设下标大于(等于)分界点的一侧为右半空间,小于分界点的一侧为左半空间。
不论左半空间和右半空间哪个是合法的,std::lower_bound()均可以找到右半空间的最小元素下标。
写代码注意点:
- while条件count>0,因为count=0表示没有数是未判断状态了,所以循环应该结束。
- if条件应该是it属于左半空间的充要条件,因为如果it满足条件直接跳到it+1,说明满足这个条件的都跳过。结合目标是找右半空间的最小元素下标可知,被跳过的都是左半空间元素。此时,由于跳过[first, first+step],共step+1个数,所以count-=step+1。
- 如果it不满足条件,那么it属于右半空间,只剩下[first,first+step-1]是未判定的元素,共count个数,所以count=step。
C++ STL中的二分法的更多相关文章
- STL中的查找算法
STL中有很多算法,这些算法可以用到一个或多个STL容器(因为STL的一个设计思想是将算法和容器进行分离),也可以用到非容器序列比如数组中.众多算法中,查找算法是应用最为普遍的一类. 单个元素查找 1 ...
- C++ STL中哈希表Map 与 hash_map 介绍
0 为什么需要hash_map 用过map吧?map提供一个很常用的功能,那就是提供key-value的存储和查找功能.例如,我要记录一个人名和相应的存储,而且随时增加,要快速查找和修改: 岳不群-华 ...
- C++ STL中的Binary search(二分查找)
这篇博客转自爱国师哥,这里给出连接https://www.cnblogs.com/aiguona/p/7281856.html 一.解释 以前遇到二分的题目都是手动实现二分,不得不说错误比较多,关于返 ...
- STL 中的map 与 hash_map的理解
可以参考侯捷编著的<STL源码剖析> STL 中的map 与 hash_map的理解 1.STL的map底层是用红黑树存储的,查找时间复杂度是log(n)级别: 2.STL的hash_ma ...
- STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- STL中的next_permutation
给定一个数组a[N],求下一个数组. 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 ..... 在STL中就有这个函数: 1.参数是(数组的第一个元素,数组的末尾),注意这是前闭后开 ...
- 3.2 STL中的函数对象类模板
*: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...
- C++的模板特化 和 STL中iterator_traits模板的偏特化
C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...
- C++的STL中vector内存分配方法的简单探索
STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux CentOS 5.2 1.代码 #include <vector> #include <stdio ...
- C++ STL中vector(向量容器)使用简单介绍
原文:http://www.seacha.com/article.php/knowledge/cbase/2013/0903/2205.html C++ vector(向量容器)是一个线性顺序结构.相 ...
随机推荐
- 实现简单的csv文件上传和bootstrap表格的下载
一.写一个简单的页面并发送文件 引入bootstrap.js,jQuery.js等,具体的网页就不细写了,很简单. 加入input框,button控件,进度条.如下: <li class=&qu ...
- [cocos2d-x]关于定时器
什么是定时器 定时器的作用就是每隔一段时间,就执行一段自定义的动作,比如飞机向前方移动,子弹的移动等等.该函数定义在CCNode头文件中,基本上cocos2dx中所有的东西都能够使用定时器. 定时器的 ...
- .NET 7新特性
2022年11月份微软推出了带有STS(标准期限支持)的.NET版本7,仅提供18个月的支持. 微软今年推出了STS版本,因为它已经在2019年提到,它将在每年11月左右发布一个新版本的.NET. 但 ...
- os 模块 sys模块 json模块
今日内容详细 os模块(重要) os模块主要与代码运行所在的操作系统打交道 import os 1.创建目录 1.创建目录(文件夹) os.mkdir(r'L4') # 只可以创建单级目录 相对路径 ...
- 如何进行动态ip的域名解析设置?
如何进行动态ip的域名解析设置?目前,有一部分域名客户出于节省成本.技术验证等因素,会把自己家里或是部门的电脑用来当做Web服务器.mail服务器或是ftp服务器.如果想提供给其他人长期浏览,一般都要 ...
- 行为型模式 - 迭代器模式iterator
模式的定义与特点 迭代器模式(iterator Pattern),为的提是可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象.多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对 ...
- 11月25日内容总结——sql查询关键字
目录 一.SQL语句查询关键字 二.前期数据准备 三.编写SQL语句的小技巧 四.查询关键字之where筛选 1.查询id大于等于3小于等于6的数据 2.查询薪资是20000或者18000或者1700 ...
- JAVA虚拟机02---JAVA虚拟机运行时数据区域简介
JAVA虚拟机运行时数据区域 1.程序计数器 1)它可以看做是当前线程执行的字节代码的行指示器,通过改变计数器的值来决定下一步执行的代码 2)它是线程私有的,每个线程都有自己的程序计数器(JAVA ...
- Google Guice 用户指南 - Ⅰ:概览
译者:kefate 原文:https://github.com/google/guice/wiki/Overview 大家好,我是kefate.今天开始我将会把Google Guice的官方文档陆续翻 ...
- xml基本学习
概念:可拓展标记语言.可拓展即标签都是自定义的.标记语言即由标签构成的语言. 功能:存储数据: 配置文件 在网络中传输 语法 基本语法: xml文件后缀名为.xml xml第一行必须定义为文档声明 x ...