容器set和multiset

一、set和multiset基础

set和multiset会根据特定的排序准则,自动将元素进行排序。不同的是后者允许元素重复而前者不允许。


需要包含头文件:

#include <set>

set和multiset都是定义在std空间里的类模板:

[cpp] view plaincopyprint?
  1. template<class _Kty,  
  2.     class _Pr = less<_Kty>,  
  3.     class _Alloc = allocator<_Kty> >  
  4. class set  
[cpp] view plaincopyprint?
  1. template<class _Kty,  
  2.     class _Pr = less<_Kty>,  
  3.     class _Alloc = allocator<_Kty> >  
  4. class multiset  

只要是可复赋值、可拷贝、可以根据某个排序准则进行比较的型别都可以成为它们的元素。第二个参数用来定义排序准则。缺省准则less是一个仿函数,以operator<对元素进行比较。

所谓排序准则,必须定义strict weak ordering,其意义如下:

1、必须使反对称的。

对operator<而言,如果x<y为真,则y<x为假。

2、必须使可传递的。

对operator<而言,如果x<y为真,且y<z为真,则x<z为真。

3、必须是非自反的。

对operator<而言,x<x永远为假。

因为上面的这些特性,排序准则可以用于相等性检验,就是说,如果两个元素都不小于对方,则它们相等。


二、set和multiset的功能

和所有关联式容器类似,通常使用平衡二叉树完成。事实上,set和multiset通常以红黑树实作而成。

自动排序的优点是使得搜寻元素时具有良好的性能,具有对数时间复杂度。但是造成的一个缺点就是:

不能直接改变元素值。因为这样会打乱原有的顺序。

改变元素值的方法是:先删除旧元素,再插入新元素。

存取元素只能通过迭代器,从迭代器的角度看,元素值是常数。


三、操作函数

构造函数和析构函数

set的形式可以是:


有两种方式可以定义排序准则:

1、以template参数定义:

[cpp] view plaincopyprint?
  1. set<int,greater<int>> col1;  
此时,排序准则就是型别的一部分。型别系统确保只有排序准则相同的容器才能被合并。

程序实例:

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. #include <set>  
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.     set<int> s1;  
  8.     set<int,greater<int> > s2;  
  9.   
  10.     for (int i = 1;i < 6;++i)  
  11.     {  
  12.         s1.insert(i);  
  13.         s2.insert(i);  
  14.     }  
  15.     if(s1 == s2)  
  16.         cout << "c1 equals c2 !" << endl;  
  17.     else  
  18.         cout << "c1 not equals c2 !" << endl;  
  19. }  
程序运行会报错。但是如果把s1的排序准则也指定为greater<int>便运行成功。

2、以构造函数参数定义。

这种情况下,同一个型别可以运用不同的排序准则,而排序准则的初始值或状态也可以不同。如果执行期才获得排序准则,而且需要用到不同的排序准则,这种方式可以派上用场。

程序实例:

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. #include "print.hpp"  
  3. #include <set>  
  4. using namespace std;  
  5.   
  6. template <class T>  
  7. class RuntimeCmp{  
  8. public:  
  9.     enum cmp_mode{normal,reverse};  
  10. private:  
  11.     cmp_mode mode;  
  12. public:  
  13.     RuntimeCmp(cmp_mode m = normal):mode(m){}  
  14.   
  15.     bool operator()(const T &t1,const T &t2)  
  16.     {  
  17.         return mode == normal ? t1 < t2 : t2 < t1;  
  18.     }  
  19.   
  20.     bool operator==(const RuntimeCmp &rc)  
  21.     {  
  22.         return mode == rc.mode;  
  23.     }  
  24. };  
  25.   
  26. typedef set<int,RuntimeCmp<int> > IntSet;  
  27.   
  28. void fill(IntSet& set);  
  29.   
  30. int main()  
  31. {  
  32.     IntSet set1;  
  33.     fill(set1);  
  34.     PRINT_ELEMENTS(set1,"set1:");  
  35.   
  36.     RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);  
  37.   
  38.     IntSet set2(reverse_order);  
  39.     fill(set2);  
  40.     PRINT_ELEMENTS(set2,"set2:");  
  41.   
  42.     set1 = set2;//assignment:OK  
  43.     set1.insert(3);  
  44.     PRINT_ELEMENTS(set1,"set1:");  
  45.   
  46.     if(set1.value_comp() == set2.value_comp())//value_comp <span style="font-family: verdana, arial, helvetica, sans-serif; ">Returns the comparison object associated with the container</span>  
  47.         cout << "set1 and set2 have the same sorting criterion" << endl;  
  48.     else  
  49.         cout << "set1 and set2 have the different sorting criterion" << endl;  
  50. }  
  51.   
  52. void fill(IntSet &set)  
  53. {  
  54.     set.insert(4);  
  55.     set.insert(7);  
  56.     set.insert(5);  
  57.     set.insert(1);  
  58.     set.insert(6);  
  59.     set.insert(2);  
  60.     set.insert(5);  
  61. }  
运行结果:


虽然set1和set2的而比较准则本身不同,但是型别相同,所以可以进行赋值操作。


非变动性操作

注意:元素比较操作只能用于型别相同的容器。

特殊的搜寻函数

赋值

赋值操作两端的容器必须具有相同的型别,但是比较准则本身可以不同,但是其型别必须相同。如果比较准则的不同,准则本身也会被赋值或交换。


迭代器相关函数


元素的插入和删除

注意:插入函数的返回值不完全相同。

set提供的插入函数:

[cpp] view plaincopyprint?
  1. pair<iterator,bool> insert(const value_type& elem);   
  2. iterator  insert(iterator pos_hint, const value_type& elem);   
multiset提供的插入函数:

[cpp] view plaincopyprint?
  1. iterator  insert(const value_type& elem);   
  2. iterator  insert(iterator pos_hint, const value_type& elem);  
返回值型别不同的原因是set不允许元素重复,而multiset允许。当插入的元素在set中已经包含有同样值的元素时,插入就会失败。所以set的返回值型别是由pair组织起来的两个值:

第一个元素返回新元素的位置,或返回现存的同值元素的位置。第二个元素表示插入是否成功。

set的第二个insert函数,如果插入失败,就只返回重复元素的位置!

但是,所有拥有位置提示参数的插入函数的返回值型别是相同的。这样就确保了至少有了一个通用型的插入函数,在各种容器中有共通接口。


注意:还有一个返回值不同的情况是:作用于序列式容器和关联式容器的erase()函数:

序列式容器的erase()函数:

[cpp] view plaincopyprint?
  1. iterator erase(iterator pos);   
  2. iterator erase(iterator beg, iterator end);  
关联式容器的erase()函数:

[cpp] view plaincopyprint?
  1. void     erase(iterator pos);   
  2. void     erase(iterator beg, iterator end);   
这完全是为了性能的考虑。因为关联式容器都是由二叉树实现,搜寻某元素并返回后继元素可能很费时。

五、set应用示例:

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. #include <set>  
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.     typedef set<int,greater<int> > IntSet;  
  8.     IntSet s1;  
  9.   
  10.     s1.insert(4);  
  11.     s1.insert(3);  
  12.     s1.insert(5);  
  13.     s1.insert(1);  
  14.     s1.insert(6);  
  15.     s1.insert(2);  
  16.     s1.insert(5);  
  17.     //the inserted element that has the same value with a element existed is emitted  
  18.   
  19.     copy(s1.begin(),s1.end(),ostream_iterator<int>(cout," "));  
  20.     cout << endl << endl;  
  21.   
  22.     pair<IntSet::iterator,bool> status = s1.insert(4);  
  23.     if(status.second)  
  24.         cout << "4 is inserted as element "  
  25.         << distance(s1.begin(),status.first) + 1 << endl;  
  26.     else  
  27.         cout << "4 already exists in s1" << endl;  
  28.     copy(s1.begin(),s1.end(),ostream_iterator<int>(cout," "));  
  29.     cout << endl << endl;  
  30.   
  31.     set<int>  s2(s1.begin(),s1.end());//default sort criterion is less<  
  32.     copy(s2.begin(),s2.end(),ostream_iterator<int>(cout," "));  
  33.     cout << endl << endl;  
  34. }  

上述程序最后新产生一个set:s2,默认排序准则是less。以s1的元素作为初值。

注意:s1和s2有不同的排序准则,所以他们的型别不同,不能直接进行相互赋值或比较。

运行结果:

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

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

相关文章

linux rom打包工具,Android rom解包打包工具

eMMC主要是针对手机和平板电脑等产品的内嵌式存储器&#xff0c;由于其在封装中集成了一个控制器&#xff0c;且提供标准接口并管理闪存等优势&#xff0c;越来越受到Android手机厂商的青睐&#xff0c;以eMMC为存储设备的android手机&#xff0c;其文件系统(system、data分区)…

winform(C#)透明方法

1.设置窗体opacity属性&#xff1a; 2.窗体的BackColor和TransparencyKey属性设置相同的值&#xff1a; 2.加using System.Runtime.InteropServices;引用然后加上以下代码&#xff1a; [StructLayout(LayoutKind.Sequential)]public struct MARGINS{public int Left;public int…

分布式缓存应用(转载的)

前言 Asp.Net中使用Couchbase——Memcached缓存入门篇 见http://www.cnblogs.com/aehyok/p/3436721.html 主要讲解Couchbase服务端的安装配置和客户端的引用调用&#xff0c;然后通过一个零配置的代码来完成最简单的代码实现调用。那么本次课先通过简单的配置文件进行配置&…

Jquery通过遍历数组给checkbox赋默认值

需求&#xff1a;有一个数组&#xff1a;(北京菜&#xff0c;粤菜)&#xff0c;checkbox如下&#xff1a; 现在想通过遍历这个数组&#xff0c;使数组里包含的值&#xff0c;在checkbox选中 代码&#xff1a; var flavors new Array([北京菜 , 粤菜]); $.each(flavors,functio…

Win8 IIS 安装和部署网站问题

安装IIS 比较win7的安装来说&#xff0c;多选了几个钩钩&#xff0c;不然会报错&#xff0c;偶就遇到这样的错误。 控制面板-》程序和功能-》启动和关闭windows功能&#xff0c;钩钩图例&#xff1a; 安装好iis后 在控制面板-》管理工具 目前只用过iis 信息管理器。 6.0 大概…

在SharePoint 2010中创建网站的权限级别

转&#xff1a;http://www.360sps.com/Item/CreatePermissionLevels.aspx 权限级别是SharePoint 2010新增加的功能&#xff0c;使我们对权限的设置又提高了一个层次。SharePoint 2010的权限级别指的是可分配给用户或用户组的单个权限组。SharePoint 2010自带的权限级别有&#…

仿新浪微盾客户端项目简介一

最经公司的项目需要实现类似于新浪微盾功能的功能&#xff0c;因此我把这个实战的demo的经历分享给大家。 新浪微盾是啥子玩意&#xff1f; 微盾是由新浪网推出的一款产生一次性动态密码的产品&#xff0c;可以用于新浪旗下各服务&#xff0c;包括新浪微博&#xff0c;新付通&a…

linux读取pdf文件字体,Linux有问必答:如何在PDF中嵌入LaTex中的所有字体

提问: 我通过编译LaTex源文件生成了一份PDF文档。然而&#xff0c;我注意到&#xff0c;并不是所有字体都嵌入到了PDF文档中。我怎样才能确保所有的字体嵌入在由LaTex生成的PDF文档中&#xff1f;当你创建一个PDF文件时&#xff0c;在PDF文件中嵌入字体是一个好主意。如果你不嵌…

CSS3 2D转换

CSS3 转换 通过CSS3转换&#xff0c;我们能够对元素进行移动、缩放、转动、拉长或拉伸。 它如何工作&#xff1f; 转换是是元素改变形状、尺寸和位置的一种效果。 你可以使用2D或3D转换你的元素。 浏览器支持 属性浏览器支持transform IE10、FireFox以及Opera支持transform…

然爸读书笔记(2014-5)----团队正能量

先说下题外话&#xff0c;今天下午吃烤肉&#xff0c;吃了2个小时&#xff0c;我擦啊&#xff0c;时间真心挺长&#xff0c;上面的图就是咯&#xff0c;你们嘴馋不咯。嘿嘿&#xff01; 今天真的是快速阅读了一本书&#xff0c;很早以前买的&#xff0c;一直没时间来看。刚看了…

ssh密钥代理转发(ssh agent forwarding)

之前一直用SecureCRT登陆服务器A然后再跳到服务器B&#xff0c;某日突然需要从另一台可信任的机器C用ssh登陆&#xff0c;ssh的key已经复制好&#xff0c;所以登陆A没有问题&#xff0c;但是登陆B会出现Pubkey Unauthorization.仔细翻查SecureCRT的设置&#xff0c;发现有密钥代…

c语言程序编程线性方程,C语言编程求解线性方程

C语言编程求解线性方程 本 科 专 业 学 年 论 文题 目 &#xff1a; 线性方程组求解方法比较姓 名 郭 凤 专 业 计算机科学与技术专业 班 级 08 级本科(2 )班 指导教师 刘 晓 娜 完成日期&#xff1a;2010 年 1 月 8 日题 目 &#xff1a; 线性方程组求解方法比较摘 要目前在许…

EISCONN的故事

在这春风明媚的日子里&#xff0c;有位T同学很苦恼。忙碌了一整天&#xff0c;有个BUG愣是定位不出来。简单描述呢&#xff0c;现象是这样子的&#xff1a; 第一次处理是正常的&#xff0c;但是后续的处理就是报错。sendto()调用错误码是 EISCONN&#xff08;已被连接&#xff…

c语言内循环,C语言循环控制语句

C语言循环控制语句是一个基于C语言的编程语句&#xff0c;该语句主要有while循环语句、do-while循环语句和for循环语句来实现循环结构。中文名C语言循环控制语句类 别while循环语句&#xff0c;do-while语句等目 地实现循环结构属 于计算机领域归 类编程语句基 …

同步,异步,多线程,你怎么看?

同步&#xff0c;异步&#xff0c;多线程&#xff0c;你怎么看&#xff1f; 原文:同步&#xff0c;异步&#xff0c;多线程&#xff0c;你怎么看&#xff1f;[原创]讲解同步与异步的帖子多如牛毛&#xff0c;个人的理解&#xff0c;简单地说同步就是串行&#xff0c;异步就是并…

openssl-1.0.0b - libssl 移植到ARM Linux

开发环境&#xff1a; ubuntu 10.04 arm-linux-gcc version 4.4.1 目标环境 友善之臂mini6410 linux-2.6.36 移植步骤 1&#xff0e;至官网下载最新的openssl&#xff0c;解压缩 2&#xff0e;cd进入openssl-1.0.0b目录 3&#xff0e;执行./Confiugre linux-elf-arm&#xff0c…

html仿qq最小化怎么实现,JS仿QQ好友列表展开、收缩功能(第一篇)

JS仿QQ好友列表展开、收缩功能(第一篇)发布时间&#xff1a;2020-10-17 14:20:03来源&#xff1a;脚本之家阅读&#xff1a;96作者&#xff1a;erdouzhang效果图如下所示&#xff1a;html:我的好友张三李四...企业好友小明小红...黑名单哈哈...css&#xff1a;ul,h3 {padding: …

Visual Studio 选择相同变量高亮

前段时间一直在使用matlab&#xff0c;今天需要使用vs2008&#xff0c;而用惯了matlab&#xff0c;习惯了其中一项选中变量高亮的设置&#xff0c;突然回来使用VS&#xff0c;感到各种不适应&#xff0c;顿时想到了一个词&#xff1a;矫情 呵呵&#xff0c;于是在网上找各种插件…

html是前段还是后端,javascript属于前端还是后端?

JavaScript是一种属于网络的脚本语言&#xff0c;已经被广泛用于Web应用开发&#xff0c;常用来为网页添加各式各样的动态功能&#xff0c;为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。前端开发和后端开发的区别在于&#xff1a…

Linux查看设置系统时区

关于时区的概念&#xff0c;其实初中地理课已经涉及&#xff0c;很多人都多少了解一些&#xff0c;可能只是细节搞不太清楚。为什么会将地球分为不同时区呢&#xff1f;因为地球总是自西向东自转&#xff0c;东边总比西边先看到太阳&#xff0c;东边的时间也总比西边的早。东边…