C++ multiset

multiset 是关联容器的一种,是排序好的集合(元素已经进行了排序),并且允许有相同的元素。

不能直接修改 multiset 容器中元素的值。因为元素被修改后,容器并不会自动重新调整顺序,于是容器的有序性就会被破坏,再在其上进行查找等操作就会得到错误的结果。因此,如果要修改 multiset 容器中某个元素的值,正确的做法是先删除该元素,再插入新元素

使用 multiset 必须包含头文件 。multiset 类模板的定义如下:

template <class Key, class Pred = less<Key>, class B = allocator<Key> > class multiset {...
};

该模板有三个类型参数:Key、Pred 和 B。类型参数可以有默认值,默认值就是某种类型。例如,Pred 类型参数的默认值就是 less 类型,B 的默认值就是 allocator 类型。

第一个类型参数说明 multiset 容器中的每个元素都是 Key 类型的。第二个类型参数 Pred 用于指明容器中元素的排序规则,在被实例化后,Pred 可以是函数对象类,也可以是函数指针类型。

multiset 内部在排序时定义了一个变量Pred op,根据表达式op(x, y)来比较两个元素 x、y 的大小。该表达式的值为 true,则说明 x 比 y 小。Pred 的默认值是 less,less 是 STL 中的函数对象类模板,其定义如下:

template <class_Tp>
struct less
{bool operator() (const _Tp &__x, const _Tp &__y) const{ return __x < __y; }
};

这说明,在默认情况下,multiset 容器中的元素是用<运算符比较大小的。例如,假设 A 是一个类的名字,可以定义一个如下的容器对象:

multiset <A> s;

由于 multiset 的类型参数可以使用默认值,因此上面的语句等价于:

multiset < int, less<A>, allocator<A> > s;

模板类 multiset < A, less, allocator > 的 insert 成员函数可以用来插入一个元素。 插入过程中需要进行元素之间的比较,可以认为 insert 成员函数中定义了一个变量 less op,用 op(x, y) 来比较元素 x、y 的大小。归根到底,还是用<运算符比较 x、y 的大小。 因此,<运算符必须经过适当重载,才可以向 multiset 容器中插人元素。

下面的程序 会编译出错:

#include <set>
using namespace std;
class A{};
int main(){multiset <A> a;a.insert( A() );  //编译出错,因为不能用“<”运算符比较两个A对象
}

multiset 的成员函数

成员函数或成员函数模板作 用
iterator find (const T & val);在容器中查找值为 val 的元素,返回其迭代器。如果找不到,返 回 end()
iterator insert( const T & val);将 val 插入容器中并返回其迭代器
void insert(iterator first, iterator last);将区间 [first, last) 中的元素插人容器
int count( const T & val);统计有多少个元素的值和 val 相等
iterator lower_bound( const T & val);查找一个最大的位置 it,使得 [begin(), it) 中所有的元素者比 val 小
iterator upper_bound( const T & val);查找一个最小的位置 it,使得 [it, end()) 中所有的元素都比 val 大
pair <iterator, iterator > equal_range (const T & val);同时求得 lower_bound 和 upper_bound
iterator erase(iterator it);删除 it 指向的元素,返回其后面的元素的迭代器
iterator erase(iterator first, iterator last);删除区间 [first, last),返回 last

multiset 及 set 中的 find 和 count 并不是用==运算符比较元素是否和待查找的值相等的。它们进行比较的原则是:如果x比y小和y比x小同时为假,就认为 x 和 y 相等。

下面通过一个例子说明 multiset 的用法。

#include <iostream>
#include <set>  //使用multiset须包含此头文件
using namespace std;
template <class T>
void Print(T first, T last)
{for (; first != last; ++first)cout << *first << " ";cout << endl;
}
class A
{
private:int n;
public:A(int n_) { n = n_; }friend bool operator < (const A & a1, const A & a2){ return a1.n < a2.n; }friend ostream & operator << (ostream & o, const A & a2){ o << a2.n; return o; }friend class MyLess;
};
class MyLess
{
public:bool operator() (const A & a1, const A & a2)  //按个位数比较大小{ return (a1.n % 10) < (a2.n % 10); }
};
typedef multiset <A> MSET1;  //MSET1 用“<”运算符比较大小
typedef multiset <A, MyLess> MSET2;  //MSET2 用 MyLess::operator() 比较大小
int main()
{const int SIZE = 6;A a[SIZE] = { 4, 22, 19, 8, 33, 40 };MSET1 m1;m1.insert(a, a + SIZE);m1.insert(22);cout << "1)" << m1.count(22) << endl;  //输出 1)2cout << "2)"; Print(m1.begin(), m1.end());  //输出 2)4 8 19 22 22 33 40MSET1::iterator pp = m1.find(19);if (pp != m1.end())  //条件为真说明找到cout << "found" << endl;  //本行会被执行,输出 foundcout << "3)"; cout << *m1.lower_bound(22)<< "," << *m1.upper_bound(22) << endl; //输出 3)22,33pp = m1.erase(m1.lower_bound(22), m1.upper_bound(22));//pp指向被删元素的下一个元素cout << "4)"; Print(m1.begin(), m1.end());  //输出 4)4 8 19 33 40cout << "5)"; cout << *pp << endl;  //输出 5)33MSET2 m2;  //m2中的元素按n的个位数从小到大排序m2.insert(a, a + SIZE);cout << "6)"; Print(m2.begin(), m2.end());  //输出 6)40 22 33 4 8 19return 0;
}

第 30 行,MSET2 类的排序规则和 MSET1 不同。MSET2 用 MyLess 定义排序规则,即 n 的个位数小的元素排在前面。

第 43、44 行,lower_bound 返回的迭代器指向第一个 22,upper_bound 返回的迭代器指向 33。

第 45 行,删除所有值为 22 的元素。erase 成员函数删除一个元素后,返回下一个元素的迭代器应该是很合理的,但是 C++ 标准委员会认为,返回下一个元素的迭代器也是需要时间开销的,如果程序员不想要这个返回值,那么这个开销就是浪费的——因此在遵循 C++ 标准的 Dev C++ 中,本行无法编译通过。但是微软公司认为应该对这一点做出改进,因此 Visual Studio 2010 将 erase 成员函数处理成返回被删元素下一个元素的迭代器。

不论在哪种编译器中,用 erase 成员函数删除迭代器 i 指向的元素后,迭代器 i 即告失效, 此时不能指望 ++i 后 i 会指向被删除元素的下一个元素;相反,++i 可能立即导致出错。如果想要得到被删除元素后面那个元素的迭代器,可以在删除前获取其迭代器并保存起来(这同样适用于 set、map、multimap 的 erase 成员函数)。事实上,如果得到了某关联容器的迭代器,则该迭代器并不会因为容器中元素的插入以及其他元素的删除而失效。只要该迭代器指向的元素没有被删除,就可以一直使用它。

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

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

相关文章

linux命令中的cp,Linux高级技术:关于cp命令中拷贝所有的写法

Linux高级技术&#xff1a;关于cp命令中拷贝所有的写法发布时间:2007-09-30 21:39:36来源:红联作者:GiftPot今天在编写一个脚本的时候&#xff0c;发现一个比较奇怪的问题&#xff1a;就是在使用cp拷贝当前目录下所有文件到目标目录的时候&#xff0c;源和目标目录大小不同。原…

C++ set

set 是关联容器的一种&#xff0c;是排序好的集合&#xff08;元素已经进行了排序&#xff09;。set 和 multiset 类似&#xff0c;它和 multiset 的差别在于 set 中不能有重复的元素。multiset 的成员函数 set 中也都有。 不能直接修改 set 容器中元素的值。因为元素被修改后…

linux内核实现ipsec,IP XFRM配置示例:利用linux kernel自带的IPSec实现,手动配置IPSec...

1、拓扑192.168.18.101 <> 192.168.18.1022、配置192.168.18.101ip xfrm state add src 192.168.18.101 dst 192.168.18.102 proto esp spi 0x00000301 mode tunnel auth md5 0x96358c90783bbfa3d7b196ceabe0536b enc des3_ede 0xf6ddb555acfd9d77b03ea3843f2653255afe8e…

linux 内核 82540网卡,Linux网卡as4.2 编译安装及配置准备

Linux网卡as4.2 编译安装及配置准备[日期&#xff1a;2008-03-28]来源&#xff1a;Linux公社作者&#xff1a;Linux整理[字体&#xff1a;大 中 小]确定make gcc kernel-devel包必须安装,没安装的话需要手动安装查看是否安装方法rpm -aq|gccrpm -aq|makerpm -aq|kernel-devel解…

C++ 容器适配器

STL 中的容器适配器有 stack、queue、priority_queue 三种。它们都是在顺序容器的基础上实现的&#xff0c;屏蔽了顺序容器的一部分功能&#xff0c;突出或增加了另外一些功能。 容器适配器都有以下三个成员函数&#xff1a; push&#xff1a;添加一个元素。top&#xff1a;返…

linux管理进程和计划任务,Linux进程和计划任务管理

本章结构#查看进程#控制进程#at一次性任务设置#crontab周期性任务设置程序和进程的关系#程序保存在硬盘、光盘等介质中的可执行代码和数据静态保存的代码#进程在cpu及内存中运行的程序代码动态执行的代码父、子进程&#xff1a;每个进程可以创建一个或多个进程查看进程ps#ps命令…

C++ stack

stack 是容器适配器的一种。要使用 stack&#xff0c;必须包含头文件 。 stack就是“栈”。栈是一种后进先出的元素序列&#xff0c;访问和删除都只能对栈顶的元素&#xff08;即最后一个被加入栈的元素&#xff09;进行&#xff0c;并且元素也只能被添加到栈顶。栈内的元素不…

C++ queue和priority_queue

queue 和 priority_queue 都是容器适配器&#xff0c;要使用它们&#xff0c;必须包含头文件 。 queue queue 就是“队列”。队列是先进先出的&#xff0c;和排队类似。队头的访问和删除操作只能在队头进行&#xff0c;添加操作只能在队尾进行。不能访问队列中间的元素。 qu…

less linux命令,less 命令用法详解

less 在 Linux 中用来查看文件&#xff0c;它可以以分页的方式显示文件内容。目前和tail 是用来查看文件的常用命令命令格式less [参数] 文件1、使用示例less a.txt用来查看文件按f 或 space 向下翻一页按b向前翻一页其实很好记f即forward 向前b即backward 向后关键最强大的一点…

STL算法分类

STL 中&#xff0c;算法就是函数模板。STL 中的算法大多数是用来对容器进行操作的&#xff0c;如排序、 查找等。大部分算法都是在头文件 中定义的&#xff0c;还有些算法用于数值处理&#xff0c;定义在头文件 中。 STL 中的算法的分类方法。 1 . 不变序列算法。 2 . 变值算法…

linux系统时间代表,Linux上有两种时间,一种是硬件时间,一种是系统时间

date 系统时间clock/hwclock 硬件时钟cal 日历date打印或设置系统日期或时间&#xff0c;以给定格式显示或设置系统时间%a显示周%A 完整显示周%b显示月份%B 完整显示月%c e.g.,Thu Mar 3 23:05:25 2005%C 显示世纪%d显示几日%D …

linux下软件包清理,Linux运维知识:如何清理Linux系统中的孤立、无用的软件包

本文主要向大家介绍了Linux运维知识的如何清理Linux系统中的孤立、无用的软件包&#xff0c;通过具体的内容向大家展现&#xff0c;希望对的大家学习Linux运维知识有所帮助。在Linux下安装软件&#xff0c;通常会自动安装一些依赖包或库。在你卸载某个软件后&#xff0c;这个软…

linux 多个定时器,timer: 一个Linux下的超级精简的多重定时器:可实现成千上万个定时任务,定时精度可达纳秒级别,且同一时间点可添加不同的任务!适用于云后台服务和嵌入式等各种环境。...

MT_Timer(MT译为Multiple或Multi)一、介绍一个Linux下的超级简洁的定时器&#xff1a;利用epoll机制和timerfd新特性实现的多重、多用、多个定时任务实现。只需要使用TIMER_CREATE()接口创建一个定时器实体&#xff0c;即可向其添加成千上万个定时任务&#xff0c;定时任务可达…

C++ bitset类

bitset 模板类由若干个位&#xff08;bit&#xff09;组成&#xff0c;它提供一些成员函数&#xff0c;使程序员不必通过位运算就能很方便地访问、修改其中的任意一位。bitset 模板类在头文件 中定义如下&#xff1a; template <size_t N> class bitset {... };size_t 可…

red flag linux指定域名,Red Flag Server 4.1 系统管理手册(适用桌面linux4.1) 6

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼第3章 文件系统管理 (三)--------------------------------------------------------------------------------3.6 LVM逻辑卷管理LVM 是 Logical Volume Manager 的简写&#xff0c;它为计算机提供了更高层次的磁盘存储解决方案&am…

什么是计算机文件

内存中存放的数据在计算机关机后就会消失。要长久保存数据&#xff0c;就要使用硬盘、光盘、U 盘等设备。为了便于数据的管理和检索&#xff0c;引入了“文件”的概念。 一篇文章、一段视频、一个可执行程序&#xff0c;都可以被保存为一个文件&#xff0c;并赋予一个文件名。…

linux下阻塞的系统调用,Linux下文件的阻塞与非阻塞对部分系统调用的影响

1.基本概念所谓的阻塞&#xff0c;即内核在对文件操作I/O系统调用时&#xff0c;如果条件不满足(可能需要产生I/O)&#xff0c;则内核会将该进程挂起。非阻塞则是发现条件不满足就会立即返回。此外需要注意的是非阻塞并不是轮询&#xff0c;不然就和阻塞没多大区别了&#xff0…

C++文件类

C 标准类库中有三个类可以用于文件操作&#xff0c;它们统称为文件流类。这三个类是&#xff1a; ifstream&#xff1a;用于从文件中读取数据。ofstream&#xff1a;用于向文件中写人数据。fstream&#xff1a;既可用于从文件中读取数据&#xff0c;又可用于 向文件中写人数据。…

window10内核Linux,windows 10中发布完整的Linux内核

5月8日消息&#xff1a; 近年来&#xff0c;微软对Linux开发者社区的支持令许多人感到惊讶&#xff0c;包括将诸如Bash shell之类的东西引入到Windows&#xff0c;或者在Windows 10中支持原生OpenSSH&#xff0c;甚至包括Windows应用商店上架了Ubuntu、SUSE Linux和Fedora。现在…

C++ open 打开文件

在对文件进行读写操作之前&#xff0c;先要打开文件。打开文件有以下两个目的&#xff1a; 1 . 通过指定文件名&#xff0c;建立起文件和文件流对象的关联&#xff0c;以后要对文件进行操作时&#xff0c;就可以通过与之关联的流对象来进行。 2 . 指明文件的使用方式。使用方…