STL算法之其它算法_中

目录

lower_bound(应用于有序区间)

upper_bound(应用于有序区间)

binary_search(应用于有序区间)

next_permutation

prev_permutation


lower_bound(应用于有序区间)

        这是二分查找(binary search)的一种版本,试图在已排序的[first,last)中寻找元素value。如果[first,last)具有与value相等的元素(s),便返回一个迭代器,指向其中第一个元素。如果没有这样的元素存在,便返回“假设这样的元素存在时应该出现的位置”。也就是说,它会返回一个迭代器,指向第一个“不小于value”的元素。如果value大于[first,last)内的任何一个元素,则返回last。以稍许不同的观点来看lower_bound,其返回值是“不破坏排序状态的原则下,可插入value的第一个位置”。如下图所示

        这个算法有两个版本,版本一采用operator<进行比较,版本二采用仿函数comp。更正式地说,版本一返回[first,last)中最远的迭代器i,是的[first,i)中的每个迭代器j都满足*j < value。版本二,满足上述迭代区间每个迭代器j,满足“comp(*j, value)为真”。

//版本一
template <class ForwardIterator, class T>
inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value) {return __lower_bound(first, last, value, distance_type(first), iterator_category(first));
}//版本二
template <class ForwardIterator, class T, class Compare>
inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) {return __lower_bound(first, last, value, comp, distance_type(first), iterator_category(first));
}

        下面是版本一的两个辅助函数。

// 版本一的forward_iterator版本
template <class ForwardIterator, class T, class Distance>
ForwardIterator __lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) {Distance len = 0;distance(first, last, len);Distance half;ForwardIterator middle;while(len > 0) {half = len >> 1;middle = first;advance(middle, half);if (*middle < value) {first = middle;++first;len = len - half - 1;}else len = half;}return first;
}// 版本一的random_access_iterator版本
template <class RandomAccessIterator, class T, class Distance>
ForwardIterator __lower_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) {Distance len = 0;distance(first, last, len);Distance half;RandomAccessIterator middle;while(len > 0) {half = len >> 1;middle = first + half;if (*middle < value) {first = middle + 1;len = len - half - 1;}else len = half;}return first;
}

对于版本二的两个辅助函数,只需将*middle < value,修改成comp(*middle, value)即可,此处不在赘述。

upper_bound(应用于有序区间)

        算法upper_bound是二分查找(binary search)法的一个版本。它试图在已排序的[first,last)中寻找value。更明确地说,它会返回“不在破坏顺序的情况下,可插入value的最后一个合适位置”。(lower_bound(应用于有序区间)中有图说明)

        由于STL规范“区间圈定”时的起头和结尾并不对称,前开后必,所以upper_bound与lower_bound返回值意义不同。如果你查找某值,而它的确出现在区间之内,则lower_bound返回的是一个指向该元素的迭代器。而uppder_bound不这么做。因为upper_bound所返回的是在不破坏排序状态的情况下,value可被插入的“最后一个”合适位置。如果value存在,那么它返回的迭代器将指向value的下一个位置,而非指向value本身。

        upper_bound有两个版本,版本一采用operator<进行比较,版本二采用仿函数comp。更正式地说,版本一返回[first,last)区间内最远的迭代i,使得[first,i)内的每个迭代器j都满足“value <*j不为真”。版本二是上述区间内的每个迭代器j都满足“comp(value, *j)不为真”。

//版本一
template <class ForwardIterator, class T>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value) {return __upper_bound(first, last, value, distance_type(first), iterator_category(first));
}//版本二
template <class ForwardIterator, class T, class Compare>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) {return __upper_bound(first, last, value, comp, distance_type(first), iterator_category(first));
}

下面是两个辅助函数

// 版本一的forward_iterator版本
template <class ForwardIterator, class T, class Distance>
ForwardIterator __upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) {Distance len = 0;distance(first, last, len);Distance half;ForwardIterator middle;while(len > 0) {half = len >> 1;middle = first;advance(middle, half);if (value < *middle)len = half;else  {first = middle;++first;len = len - half - 1;}}return first;
}// 版本一的random_access_iterator版本
template <class RandomAccessIterator, class T, class Distance>
ForwardIterator __upper_bound(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) {Distance len = 0;distance(first, last, len);Distance half;RandomAccessIterator middle;while(len > 0) {half = len >> 1;middle = first + half;if (value < *middle) len = half;else {first = middle + 1;len = len - half - 1;}}return first;
}

对于版本二的两个辅助函数,只需将value < *middle,修改成comp(value, *middle)即可,此处不在赘述。

binary_search(应用于有序区间)

        算法binary_search是一种二分查找法,试图在已排序的[first, last)中寻找元素value。如果[first,last)内有等同于value的元素,便返回true,否则返回false。

        返回单纯的bool或许不能满足需求,前面所介绍的lower_bound,upper_bound能提供额外信息。事实上binary_search便是利用lower_bound先找出迭代器,而后对迭代器进行解引用并于value进行比较,判断值是否存在。

        binary_search的第一个版本采用operator<进行比较,第二版本采用仿函数comp进行比较。

        正式地说,当且仅当[first,last)中存在一个迭代器i是的*i<value和value<*i皆不为真,则第一个版本返回true。第二个版本则是上述迭代器i,满足comp(*i, value)和comp(value,*i)皆不为真,则第二版本返回true。

//版本一
template <class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value) {ForwardIterator I = lower_bound(first, last, value);return I != last && !(value < *I);
}//版本二
template <class ForwardIterator, class T, class Compare>
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) {ForwardIterator I = lower_bound(first, last, value, comp);return I != last && !comp(value, *I);
}

next_permutation

        STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和pre_permutation.首先我们必须了解什么是“下一个”排列组合,什么事“前一个”排列组合。考虑三个字符所组成的序列{a,b,c}。这个序列有六个可能得排列组合:abc,acb,bac,cab,cba。这些排列组合根据less-than操作符做字典顺序的排序。也就是,abc名列第一,因为每一个元素都小于其后的元素。acb是次一个排列组合,因为它是固定了a(序列内最小元素)之后所做的新组合。同样的道理,那些固定b而做的排列组合,在次序上将先于那些固定c而做的排列组合。以bac和bca为例。bac在bca之前,因为序列ac小于ca。面对bca,我们可以说前一个排列组合是bac。而其后一个排列组合是cab。序列abc没有前一个排列组合,cba没有后一个排列组合。

        next_permutation()会取得[first,last)所标示之序列的下一个排列组合。如果没哟下一个排列组合,便返回false;否则返回true。

        这个算法有两个版本。版本一使用元素型别所提供的less-than操作符来决定下一个排列组合,版本二则是以仿函数comp来决定。

        稍后将出现的实现,简述如下,符号如下图所示:

        首先,从尾端往前寻找两个相邻的元素,令第一个元素为*i,第二个元素为*ii,且满足*i<*ii.找到这样一组相邻元素后,再从最尾端开始往前检验,找出第一个大于*i的元素,令为*j,将i,j元素对调,再将II之后的所有元素颠倒排序。此即所求值下一个排列组合。

        举个实例,假设手上有序列{0,1,2,3,4},下图便是套用上述演算法则,一步一步获得“下一个”排列组合。图中只框出那符合“第一元素为I,第二元素为*ii,且满足*i<*ii”的相邻元素。

以下便是版本一的实现细节。

template <class BidirectionalIterator>
bool next_permutation(BidirectionalIterator first, BidirectionalIterator last) {if (first == last) return false;BidirectionalIterator I = first;++I;if (I = last) return false;I = last;--I;for (;;) {BidirectionalIterator II = I;--I;if (*I < *II) {BidirectionalIterator J = last;while(!(*I < *--J);iter_swap(I,J);reverse(II, last);return true;}if (I == first) {            // 进行到了最前面都未找到符合条件的元素reverse(first, last);    // 全部重排,重新再来一遍?return false;}}
}

版本二只是将operator<用comp替换,此处不在罗列代码。

prev_permutation

        所谓“前一个”排列组合,其意义已在上一节阐述。实际做法简述如下,从最尾端开始往前寻找两个相邻元素,令第一个元素为*i,第二个元素为*ii,且满足*i>*ii.找到这样一组相邻元素后,再从尾端开始往前检验,找到第一个小于*i的元素,令为*j,将i,j元素对调,再将ii之后的所有元素颠倒排序。此即前一个排列组合。

template <class BidirectionalIterator>
bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last) {if (first == last) return false;BidirectionalIterator I = first;++I;if (I = last) return false;I = last;--I;for (;;) {BidirectionalIterator II = I;--I;if (*II < *I) {BidirectionalIterator J = last;while(!(*--J < *I );iter_swap(I, J);reverse(II, last);return true;}if (I == first) {            // 进行到了最前面都未找到符合条件的元素reverse(first, last);    // 全部重排,重新再来一遍?return false;}}
}

代码如下:版本二只是将operator<用comp替换,此处不在罗列代码。

参考文档《STL源码剖析》---侯捷

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/888214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GEE教程——Google Earth Engine 处理和分析刚果民主共和国(DR Congo)地区的 Landsat 8 图像(NDVI和NDWI)

目录 简介 函数 sort(property, ascending) Arguments: Returns: Collection size() Arguments: Returns: Integer 代码解释 代码 结果 简介 GEE教程——Google Earth Engine 处理和分析刚果民主共和国(DR Congo)地区的 Landsat 8 图像(NDVI和NDWI) 函数 sor…

[高阶数据结构六]最短路径算法

1.前言 最短路径算法是在图论的基础上讲解的&#xff0c;如果你还不知道图论的相关知识的话&#xff0c;可以阅读下面几篇文章。 [高阶数据结构四] 初始图论_初始图结构-CSDN博客 [高阶数据结构五] 图的遍历和最小生成树_图的遍历和生成树求解-CSDN博客 本章重点&#xff1a;…

Meta Reality Labs的VR/AR投资战略转向:内部视角与市场影响

最近,关于Meta(原Facebook)计划减少其在消费者虚拟现实(VR)领域的投资而增加对增强现实(AR)眼镜的投资的消息引起了广泛讨论。这一战略调整不仅反映了Meta对未来技术趋势的看法,也揭示了公司在面对激烈的市场竞争时所采取的新方向。本文将从不同角度探讨此次战略转向的…

ASP.NET Core项目中使用SqlSugar连接多个数据库的方式

之前学习ASP.NETCore及SqlSugar时都是只连接单个数据库处理数据&#xff0c;仅需在Program文件中添加ISqlSugarClient的单例即可&#xff08;如下代码所示&#xff09;。 builder.Services.AddSingleton<ISqlSugarClient>(s > {SqlSugarScope sqlSugar new SqlSugar…

flutter_quill如何设置Editor中的文字为富文本

比如一个场景 在输入框中&#xff0c;某某某 是一个颜色&#xff0c;其他文本是一个颜色 这里要注意 const QuillEditor({required this.controller,required this.focusNode,required this.scrollController,required this.scrollable,required this.padding,required this…

uniapp:封装商品列表为组件并使用

封装商品列表为组件并使用 商品组件封装 <template><!-- 商品列表 --><view class"goods_list"><view class"goods_item" v-for"item in goods" :key"item.id"><image :src"item.img_url">…

【AI系统】LLVM 架构设计和原理

LLVM 架构设计和原理 在上一篇文章中&#xff0c;我们详细探讨了 GCC 的编译过程和原理。然而&#xff0c;由于 GCC 存在代码耦合度高、难以进行独立操作以及庞大的代码量等缺点。正是由于对这些问题的意识&#xff0c;人们开始期待新一代编译器的出现。在本节&#xff0c;我们…

【C语言】结构体(二)

一&#xff0c;结构体的初始化 和其它类型变量一样&#xff0c;对结构体变量可以在定义时指定初始值 #include <stdio.h> #include <stdlib.h> struct books // 结构体类型 {char title[50];char author[50]; //结构体成员char subject[100];int book_id; }…

【docker】docker网络六种网络模式

Docker 网络模式总结 网络模式描述使用场景bridge默认的网络模式&#xff0c;容器之间通过虚拟网桥通信&#xff0c;容器与宿主机隔离。单机部署、本地开发、小型项目host容器与宿主机共享网络堆栈&#xff0c;容器直接使用宿主机的 IP 地址。高性能网络应用、日志处理、大量与…

四、初识C语言(4)

一、作业&#xff1a;static修饰局部变量 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> //作业&#xff1a;static修饰局部变量 int sum (int a) {int c 0;static int b 3;c 1;b 2;return (abc); } int main() {int i 0;int a …

【python】类方法和静态方法

类方法 通过classmethod装饰器实现 class A(object):bar 1classmethoddef class_foo(cls):print Hello, , clsprint cls.bar>>> A.class_foo() # 直接通过类来调用方法 Hello, <class __main__.A> 1在上面&#xff0c;我们使用了 classmethod 装饰方法 clas…

Linux 中的 ls 命令:从使用到源码解析

ls 命令是 Linux 系统中最常用和最基本的命令之一。下面将深入探讨 ls 命令的使用方法、工作原理、源码解析以及实际应用场景。 1. ls 命令的使用** ls 命令用于列出目录内容&#xff0c;显示文件和目录的详细信息。 1.1 基本用法 ls [选项] [文件或目录]例如&#xff1a; …

SQL 中SET @variable的使用

在 SQL 中&#xff0c;SET variable 用于声明和赋值用户定义的变量。具体来说&#xff0c; 符号用于表示一个局部变量&#xff0c;可以在 SQL 语句中存储和使用。它通常在存储过程、函数或简单的 SQL 查询中使用。 1. 声明并赋值给变量 你可以使用 SET 语句给一个变量赋值。例…

The selected directory is not a valid home for Go SDK

在idea里配置go语言的环境时&#xff0c;选择go语言的安装目录&#xff0c;一直提示这个 The selected directory is not a valid home for Go SDK后来查了一下&#xff0c;发现原来idea识别不出来 需要改一下配置文件&#xff0c;找到go环境的安装目录&#xff0c;我是默认安…

Leetcode581. 最短无序连续子数组(HOT100)

链接 我的代码&#xff1a; class Solution { public:int findUnsortedSubarray(vector<int>& nums) {vector<int> res nums;sort(res.begin(),res.end());int l 0,r nums.size()-1;while(nums[l]res[l]){l;if(lnums.size()){return 0;}}while(nums[r]res…

SQL优化与性能——数据库事务管理

数据库事务管理是数据库系统中至关重要的一部分&#xff0c;确保了数据的一致性、完整性、可靠性和隔离性。尤其在高并发、高负载的系统中&#xff0c;事务管理的设计和实现直接影响到系统的稳定性和性能。本章将详细探讨以下内容&#xff1a;事务的ACID特性、使用 BEGIN、COMM…

CentOS修改yum.repos.d源,避免“Could not resolve host: mirrorlist.centos.org”错误

1、问题现象 由于CentOS停止维护&#xff0c;mirrorlist.centos.org网站也关闭不可访问。导致CentOS默认配置的yum.repos.d源也不可用&#xff0c;所以执行yum命令会报“Could not resolve host: mirrorlist.centos.org”错误。具体如下&#xff1a; Could not retrieve mirror…

【Robocasa】Code Review

文章目录 OverviewalgoInitializationImportant Class MethodsTrain LoopTest Time ConfigsdemoConfig FactoryConfig StructureConfig Locking默认锁定状态配置修改的上下文管理器 dataset示例数据集对象参数说明 model基础模块EncoderCoreVisualCoreScanCore随机化器 (Random…

【单细胞数据库】癌症单细胞数据库CancerSEA

数据库地址&#xff1a;home (hrbmu.edu.cn) Cite Huating Yuan, Min Yan, Guanxiong Zhang, Wei Liu, Chunyu Deng, Gaoming Liao, Liwen Xu, Tao Luo, Haoteng Yan, Zhilin Long, Aiai Shi, Tingting Zhao, Yun Xiao, Xia Li, CancerSEA: a cancer single-cell state atlas…

在物联网软件开发中,常见的通信协议有哪些

在物联网 (IoT) 软件开发中&#xff0c;通信协议是关键部分&#xff0c;用于设备间以及设备与服务器之间的数据传输。以下是我收集总结的常见的通信协议及其特点&#xff1a; 1. 应用层协议 这些协议负责数据的格式化、传输和解读&#xff0c;常用于 IoT 设备与云服务或其他设…