set,multiset容器类型

2024-04-04 13:18
文章标签 类型 set 容器 multiset

本文主要是介绍set,multiset容器类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

set和multiset会根据特定的排序准则,自动将元素排序。两者不同处在于multiset允许元素重复而set不允许。

一、集和多集(set 和multiset 容器类)

在使用set和multiset之前,先必须包含头文件<set>
#include <set>
在其中,set和multiset被定义为命名空间std内的class template:

namespace std {  template<class T,  <class Compare = less<T>,  <class Allocator = allocator<T> >  class set;  template<class T,  <class Compare = less<T>,  <class Allocator = allocator<T> >  class multiset;  
}  
第一个template参数当做元素的value。
第二个参数可有可无,用它来定义排序准则。缺省准则less-这是一个仿函数,以opertor<对元素进行比较,以便完成排序。
第三个template参数可有可无,用它来定义内存模型。缺省的内存模型是allocator,由C++标准程序库提供。
一个集合(set)是一个容器,它其中所包含的元素的值是唯一的。
集和多集的区别是:set支持唯一键值,set中的值都是特定的,而且只出现一次;而multiset中可以出现副本键,同一值可以出现多次。

构造:

explicit set(const Compare&=compare());
如:set<int,less<int> > set1;

less<int>是一个标准类,用于形成升序排列函数对象。降序排列是用greater<int>。

Template<class InputIterator> 
set(InputIterator, InputIterator, const Compare&=compare());

如:set<int ,less<int> >set2(vector1.begin(),vector1.end());
通过指定某一预先定义的区间来初始化set对象的构造函数。
set(const set<Key,Compare&>);
如:set<int ,less<int> >set3(set2);

set<int> c;
set<int> c(op);
set<int> c1(c2);
set<int> c(beg,end,op);
c.size();//集合中元素的数目
c.empty();//如果集合为空,返回true(真)
c.max_size();//返回集合能容纳的元素的最大限值
c.count(elem);//返回某个值元素的个数
c.find(elem);//返回一个指向被查找到元素的迭代器
c.lower_bound(elem);//返回指向大于(或等于)某值的第一个元素的迭代器
c.upper_bound(elem);//返回大于某个值元素的迭代器
c.equal_range(elem);//返回集合中与给定值相等的上下限的两个迭代器
c.swap(c1)或全局函数swap(c,c1); //交换两个集合变量
c.begin();//返回指向第一个元素的迭代器
c.end();//返回指向最后一个元素之后的迭代器,不是最后一个元素
c.rbegin();//返回指向集合中最后一个元素的反向迭代器
c.rend();//返回指向集合中第一个元素的反向迭代器
c.insert(elem);//在集合中插入元素
c.insert(pos,elem);
c.insert(beg,end);
c.erase(elem);//返回移除元素个数,删除集合中的元素
c.erase(pos);//无返回值
c.erase(beg,end);//无返回值
c.clear();//清除所有元素
//set提供如下接口
pair<iterator, bool> insert(const value_type &elem);
iterator insert(iterator pos_hint, const value_type &elem);
//multiset提供如下接口
iterator insert(const value_type &elem);
iterator insert(iterator pos_hint, const value_type &elem); //
typedef set<int, greater<int> > IntSet;
typedef multiset<int, greater<int> > IntSet;

get_allocator() 返回集合的分配器

key_comp() 返回一个用于元素间值比较的函数

value_comp() 返回一个用于比较元素间的值的函数

集合操作:

std::set_intersection() ;//这个函数是求两个集合的交集。
std::set_union() ;//求两个集合的并集
std::set_difference(); //差集
std::set_symmetric_difference(); //得到的结果是第一个迭代器相对于第二个的差集并 上第二个相当于第一个的差集
struct compare{bool operator ()(string s1,string s2){return s1>s2;}///自定义一个仿函数
};
std::set<string,compare> s;
string str[10];
string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//求交集,返回值指向str最后一个元素的尾端
end = std::set_union(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//并集
end = std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//s2相对于s1的差集
end = std::set_difference(s2.begin(),s2.end(),s.begin(),s.end(),str,compare());//s1相对于s2的差集
end = std::set_symmetric_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//上面两个差集的并集

二、应用实例

#include <iostream>
#include <set>using namespace std;int main(int argc, char **argv)
{//type of the collection : sets//no duplicates//elements are integral values// descending ordertypedef set<int, greater<int> > IntSet;//empty set containerIntSet coll;//insert elements in random ordercoll.insert(4);coll.insert(3);coll.insert(5);coll.insert(1);coll.insert(6);coll.insert(2);coll.insert(5);//iterate over all elements and print themIntSet::iterator pos;for (pos = coll.begin(); pos != coll.end(); ++ pos) {cout<< *pos<<"\n";}//insert 4 again and process return valuepair<IntSet::iterator, bool> status = coll.insert(4);if (status.second) {cout<<"4 inserted as element "<<distance(coll.begin(), status.first) + 1<<endl;} else {cout<<"4 already exists"<<endl;}copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout<<endl;//assign elements to anthor set with ascending order//set<int>  coll2(coll.begin(), coll.end());//copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));//remove all the elements up to element with 3coll.erase(coll.begin(), coll.find(3));copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout<<endl;//remove all elements with value 5int num = coll.erase(2);cout<<num<<" elements removed "<<endl;copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));cout<<endl;cout<<endl;return 0;
}
运行结果:


#include <iostream>
#include <set>
#include <string>
#include <algorithm>using namespace std;struct compare
{bool operator() (string s1,string s2){return s1>s2;}///自定义一个仿函数
};int main()
{typedef std::set<string,compare> _SET;_SET s;s.insert(string("sfdsfd"));s.insert(string("apple"));s.insert(string("english"));s.insert(string("dstd"));cout<<"s1:"<<endl;std::set<string,compare>::iterator it = s.begin();while(it!=s.end())cout<<*it++<<" ";cout<<endl<<"s2:"<<endl;_SET s2;s2.insert(string("abc"));s2.insert(string("apple"));s2.insert(string("english"));it = s2.begin();while(it!=s2.end())cout<<*it++<<" ";cout<<endl<<endl;string str[10];string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//求交集,返回值指向str最后一个元素的尾端cout<<"result of set_intersection s1,s2:"<<endl;string *first = str;while(first<end)cout <<*first++<<" ";cout<<endl<<endl<<"result of set_union of s1,s2"<<endl;end = std::set_union(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//并集 first = str;while(first<end)cout <<*first++<<" ";cout<<endl<<endl<<"result of set_difference of s2 relative to s1"<<endl;first = str;end = std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//s2相对于s1的差集 while(first<end)cout <<*first++<<" ";cout<<endl<<endl<<"result of set_difference of s1 relative to s2"<<endl;first = str;end = std::set_difference(s2.begin(),s2.end(),s.begin(),s.end(),str,compare());//s1相对于s2的差集while(first<end)cout <<*first++<<" ";cout<<endl<<endl;first = str;end = std::set_symmetric_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//上面两个差集的并集 while(first<end)cout <<*first++<<" ";cout<<endl;return 0;
}
运行结果:


三、元素的添加准则

#include <iostream>
#include <set>
#include <string>using namespace std;//type for sorting criterion
template <class T>
class RuntimeCmp {public:enum cmp_mode {normal,reverse};private:cmp_mode mode;public://constructor for sorting criterion//default criterion uses value normalRuntimeCmp (cmp_mode m = normal) : mode(m) {// ...} //comparsion of elementsbool operator() (const T &t1, const T &t2) const {return mode == normal ? t1 < t2 : t2 < t1;} //comparsion of sorting criteriabool operator== (const RuntimeCmp &rc) {return mode == rc.mode;}
};//type of a set that uses this sorting criterion
typedef set<int, RuntimeCmp<int> > IntSet;//foward declaration
void fill(IntSet& iset);
void print(const string name, const IntSet &iset);int main(int argc, char **argv)
{//create, fill ,and print set with normal element order//uses default sorting criterionIntSet coll;fill(coll);print("coll", coll);//create sorting criterion with reverse element orderRuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);//create, fill ,and print set with reverse element orderIntSet coll2(reverse_order);fill(coll2);print("coll2", coll2);//assign elements AND sorting criterioncoll = coll2;coll.insert(3);print("coll", coll);//just to make sure ....if (coll.value_comp() == coll2.value_comp()) {cout<<"coll and coll2 have same sorting criterion"<<endl;} else {cout<<"coll and coll2 have different sorting criterions"<<endl;}return 0;
}void print(const string name, const IntSet &iset)
{cout<<name<<" : ";copy(iset.begin(), iset.end(), ostream_iterator<int>(cout, " "));cout<<endl;
}void fill(IntSet &iset)
{//fill insert elements in random orderiset.insert(4);iset.insert(7);iset.insert(5);iset.insert(1);iset.insert(6);iset.insert(2);iset.insert(5);
}

运行结果:


         在我的印象中,set就是一个元素不重复的集合,而事实上也正是这样的。无论从MSDN还是任何其它地方,都会告诉我们set的元素不可以重复。反之,只要元素不重复,就可以顺利的放入到set中。看起来这实在是再清楚不过了,但是仔细想一想的话,就会发现,话说只要不重复的元素就可以被放入到一个set中,但是什么样的元素是不重复的元素呢?或者说,什么样的元素是互不相同的呢?对于内置数据类型,也就是传说中的primary data type,像int 、 double、unsigned,甚至string,这些元素的“相同”非常容易理解,那么对于自定义类型呢?什么样的数据是相同的呢?什么样的数据又是不同的呢?

        在以前学习STL的时候,曾经学到过,如果要将自定义的类型放入到set中的话,就需要重载“<”符号,原因是set是一个有序的集合,集合会按照“<”比较的大小,默认按照从小到大的顺序排列。假设我现在设计如下类型:

class MyType
{public:	int a, b, c;
}

这是,为了让MyType类型可以顺利的放进set中,我必须重载“<”,这时问题来了,要如何重呢?载这类三个型有个数据成员,我能不能要求按排照a的大小列,如果a相等的话就随便按照b或者c的大小排列呢?如果近实现按照a的大小排列的话,重载函数如下:

bool operator< (const MyType& myType) const
{return a < myType.a;
}
看起来简单明了,但是事实真的是这样吗?如果我声明一个set,并在其中放入MyType(1,2,3)、MyType(1,2,4)我能成功吗? 实验了一下,结果如下:

测试时用的代码是这样的:
#include <iostream>
#include <set>
using namespace std;
class MyType
{public:int a, b, c;MyType(int a, int b, int c):a(a), b(b), c(c) { }bool operator< (const MyType& myType) const{return a < myType.a;}
};int main()
{set<MyType> se;MyType type1(1,2,3);MyType type2(1,2,4);se.insert(type1);se.insert(type2);cout<<"The set size:"<<se.size()<<endl;cout<<"Elements in the set as follows:"<<endl;for(set<MyType>::iterator it = se.begin(); it != se.end(); it++) {cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";}cout<<endl;return 0;
}
      结果很明显,当我已经把MyType(1,2,3)放到set中之后,就不能把MyType(1,2,4)放进去了。但是为什么呢?这两个对象看起来确实不一样啊!STL在比较是否相同的时候不是要比较每一个数据成员的吗?从上述的例子中,看到的确实不是这样的,STL不会自动的做任何比较,它仅对你说明过的动作干一些指定的活儿。在重载“<”的时候,当只指定众多数据成员中的一部分的时候,如果这部分都相同的话,set就认为是同一个元素了。就如上述所示一样,重载的时候仅作了a的比较,而没有说明如果a相同的话,是否对剩下的元素进行比较。这样一来,set认为MyType(1,2,3)和MyType(1,2,4)是一样的。要让set正确的进行大小的比较,针对自定义类型,就必须说明所有的数据成员的比较情况。如上述的例子的“<”重载,应该这样写:
bool operator< (const MyType& myType) const 
{return a < myType.a ? true : (b < myType.b ? true : c < myType.c);
}
这样一来,就完全说明了每一个数据成员的比较关系,set就可以正常工作了。还是MyType(1,2,3)、MyType(1,2,4)两个元素,这回运行的结果如下:

运行代码为:
#include <iostream>
#include <set>
using namespace std;
class MyType
{public:int a, b, c;MyType(int a, int b, int c):a(a), b(b), c(c) { }bool operator< (const MyType& myType) const {return a < myType.a ? true : (b < myType.b ? true : c < myType.c);}
};int main()
{set<MyType> se;MyType type1(1,2,3);MyType type2(1,2,4);se.insert(type1);se.insert(type2);cout<<"The set size:"<<se.size()<<endl;cout<<"Elements in the set as follows:"<<endl;for(set<MyType>::iterator it = se.begin(); it != se.end(); it++) {cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";}cout<<endl;return 0;
}






这篇关于set,multiset容器类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/875875

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

Mysql BLOB类型介绍

BLOB类型的字段用于存储二进制数据 在MySQL中,BLOB类型,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储的大小不同。 TinyBlob 最大 255 Blob 最大 65K MediumBlob 最大 16M LongBlob 最大 4G