C++ Set & MultiSet
转自http://www.cppblog.com/wanghaiguang/archive/2012/06/05/177627.html
STL Set介绍
集合(Set)是一种包含已排序对象的关联容器。多元集合(MultiSets)和集合(Sets)相像,只不过支持重复对象,其用法与set基本相同。
Set 又称集合,实际上就是一组元素的集合,但其中所包含的元素的值是唯一的,且是按一定顺序排列的,集合中的每个元素被称作集合中的实例。因为其内部是通过链表的方式来组织,所以在插入的时候比vector 快,但在查找和末尾添加上比vector 慢。
multiset 是多重集合,其实现方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是说集合中的同一个元素可以出现多次。
构造:
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);
方法:
1.begin() 返回指向第一个元素的迭代器
2.clear() 清除所有元素
3.count() 返回某个值元素的个数
4.empty() 如果集合为空,返回true
5.end() 返回指向最后一个元素的迭代器
6.equal_range() 返回第一个>=关键字的迭代器和>关键字的迭代器
      语法:
      pair <iterator,iterator>equal_range( const key_type &key );
      //key是用于排序的关键字
      Set<int> ctr;
      例如:
      Pair<set<int>::iterator,set<int>::iterarot>p;
      For(i=0;i<=5;i++) ctr.insert(i);
      P=ctr.equal_range(2);
      那么*p.first==2;*p.second==3;
7.erase() 删除集合中的元素
      语法:
      iterator erase( iterator i ); //删除i位置元素
      iterator erase( iterator start, iterator end );
      //删除从start开始到end(end为第一个不被删除的值)结束的元素
      size_type erase( const key_type &key );
      //删除等于key值的所有元素(返回被删除的元素的个数)
      //前两个返回第一个不被删除的双向定位器,不存在返回末尾
      //第三个返回删除个数
8.find() 返回一个指向被查找到元素的迭代器
      语法:
      iterator find( const key_type &key );
      //查找等于key值的元素,并返回指向该元素的迭代器;
      //如果没有找到,返回指向集合最后一个元素的迭代器
9.get_allocator() 返回集合的分配器
10.insert() 在集合中插入元素
      语法:
      iterator insert( iterator i, const TYPE &val ); //在迭代器i前插入val
      void insert( input_iterator start, input_iterator end );
      //将迭代器start开始到end(end不被插入)结束返回内的元素插入到集合中
      pair insert( const TYPE &val );
      //插入val元素,返回指向该元素的迭代器和一个布尔值来说明val是否成功被插入
      //应该注意的是在集合(Sets中不能插入两个相同的元素)
11.lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器
      语法:
      iterator lower_bound( const key_type &key );
      //返回一个指向大于或者等于key值的第一个元素的迭代器
12.key_comp() 返回一个用于元素间值比较的函数
      语法:
      key_compare key_comp();
      //返回一个用于元素间值比较的函数对象
13.max_size() 返回集合能容纳的元素的最大限值
14.rbegin() 返回指向集合中最后一个元素的反向迭代器
      示例:
      Set<int> ctr;
      Set<int>::reverse_iterator rcp;
      For(rcp=ctr.rbegin();rcp!=ctr.rend();rcp++)
      Cout<<*rcp<<” ”;
15.rend() 返回指向集合中第一个元素的反向迭代器
16.size() 集合中元素的数目
17.swap() 交换两个集合变量
      语法:
      void swap( set &object ); //交换当前集合和object集合中的元素
18.upper_bound() 返回大于某个值元素的迭代器
      语法:
      iterator upwer_bound( const key_type &key );
      //返回一个指向大于key值的第一个元素的迭代器
19.value_comp() 返回一个用于比较元素间的值的函数
      语法:
      iterator upper_bound( const key_type &key );//返回一个用于比较元素间的值的函数对象
20.Set集合的并,交和差
set_union(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));
set_intersection(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));
set_difference(a.begin(),a.end(),b.begin(),b.end(),insert_iterator<set<int> >(c,c.begin()));
以下转自:http://blog.csdn.net/wangji163163/article/details/3740948
Set是关联容器。其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值,set拥有和list相同的特性:当对他进行插入和删除操作的时候,操作之前的迭代器依然有效。当然删除了的那个就没效了。Set的底层结构是RB-tree,所以是有序的。
stl中特别提供了一种针对set的操作的算法:交集set_intersection,并集set_union,差集set_difference。对称差集set_symeetric_difference,这些算法稍后会讲到。
一:set模板类的声明。
2 class Key,
3 class Traits=less<Key>,
4 class Allocator=allocator<Key>
5 >
6 class set。
其中个参数的意义如下:
key:要放入set里的数据类型,可以是任何类型的数据。
Traits:这是一个仿函数(关于仿函数是什么,我后面的文章会讲到)。提供了具有比较功能的仿函数,来觉得元素在set里的排列的顺序,这是一个可选的参数,默认的是std::less<key>,如果要自己提供这个参数,那么必须要遵循此规则:具有两个参数,返回类型为bool。
Allocator:空间配置器,这个参数是可选的,默认的是std::allocator<key>.
二:set里的基本操作
我们可以通过下面的方法来实例化一个set对象
std::set<int> s;那个s这个对象里面存贮的元素是从小到大排序的,(因为用std::less作为比较工具。)
如果要想在s里面插入数据,可以用inset函数(set没用重载[]操作,因为set本生的值和索引是相同的)
s.insert(3);s.insert(5).....
因为set是集合,那么集合本身就要求是唯一性,所以如果要像set里面插入数据和以前的数据有重合,那么插入不成功。
可以通过下面的方法来遍历set里面的元素
2 while(it!=s.end())
3 {
4 cout<<*it++<<endl;//迭代器依次后移,直到末尾。
5 }
如果要查找一个元素用find函数,it = s.find(3);这样it是指向3的那个元素的。可以通过rbegin,rend来逆向遍历
2
3 while(it!=s.rend())
4
5 {cout<<*it++<<endl;}
还有其他的一些操作在这就不一一列出了。
三:与set相关的一组算法
set_intersection() :这个函数是求两个集合的交集。下面是stl里的源代码
2 class _InIt2,
3 class _OutIt> inline
4 _OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1,
5 _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)
6 { // AND sets [_First1, _Last1) and [_First2, _Last2), using operator<
7 for (; _First1 != _Last1 && _First2 != _Last2; )
8 if (*_First1 < *_First2)
9 ++_First1;
10 else if (*_First2 < *_First1)
11 ++_First2;
12 else
13 *_Dest++ = *_First1++, ++_First2;
14 return (_Dest);
15 }
这是个模板函数,从上面的算法可以看出,传进去的两个容器必须是有序的。_Dest指向输出的容器,这个容器必须是预先分配好空间的,否则会出错的,返回值指向保存结果的容器的尾端的下一个位置。eg.
2
3 std::set_difference():差集
4
5 set_symmetric_difference():得到的结果是第一个迭代器相对于第二个的差集并上第二个相当于第一个的差集。代码:
6
7 struct compare
8 {
9 bool operator ()(string s1,string s2)
10 {
11 return s1>s2;
12 }///自定义一个仿函数
13 };
14 int main()
15 {
16 typedef std::set<string,compare> _SET;
17 _SET s;
18 s.insert(string("sfdsfd"));
19 s.insert(string("apple"));
20 s.insert(string("english"));
21 s.insert(string("dstd"));
22 cout<<"s1:"<<endl;
23 std::set<string,compare>::iterator it = s.begin();
24 while(it!=s.end())
25 cout<<*it++<<" ";
26 cout<<endl<<"s2:"<<endl;
27 _SET s2;
28 s2.insert(string("abc"));
29 s2.insert(string("apple"));
30 s2.insert(string("english"));
31 it = s2.begin();
32 while(it!=s2.end())
33 cout<<*it++<<" ";
34 cout<<endl<<endl;
35
36 string str[10];
37 string *end = set_intersection(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//求交集,返回值指向str最后一个元素的尾端
38 cout<<"result of set_intersection s1,s2:"<<endl;
39 string *first = str;
40 while(first<end)
41 cout <<*first++<<" ";
42 cout<<endl<<endl<<"result of set_union of s1,s2"<<endl;
43 end = std::set_union(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//并集
44 first = str;
45 while(first<end)
46 cout <<*first++<<" ";
47 cout<<endl<<endl<<"result of set_difference of s2 relative to s1"<<endl;
48 first = str;
49 end = std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//s2相对于s1的差集
50 while(first<end)
51 cout <<*first++<<" ";
52 cout<<endl<<endl<<"result of set_difference of s1 relative to s2"<<endl;
53 first = str;
54 end = std::set_difference(s2.begin(),s2.end(),s.begin(),s.end(),str,compare());//s1相对于s2的差集
55
56 while(first<end)
57 cout <<*first++<<" ";
58 cout<<endl<<endl;
59 first = str;
60 end = std::set_symmetric_difference(s.begin(),s.end(),s2.begin(),s2.end(),str,compare());//上面两个差集的并集
61 while(first<end)
62 cout <<*first++<<" ";
63 cout<<endl;
64 }
65
66 set<int> s3 ;
67 set<int>::iterator iter = s3.begin() ;
68 set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(s3,iter));
69 copy(s3.begin(),s3.end(), ostream_iterator<int>(cout," "));
C++ Set & MultiSet的更多相关文章
- C++ std::multiset
		
std::multiset template < class T, // multiset::key_type/value_type class Compare = less<T>, ...
 - Guava学习笔记:Guava新增集合类型-Multiset
		
Guava引进了JDK里没有的,但是非常有用的一些新的集合类型.所有这些新集合类型都能和JDK里的集合平滑集成.Guava集合非常精准地实现了JDK定义的接口.Guava中定义的新集合有: Multi ...
 - [Google Guava]学习--新集合类型Multiset
		
Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关.Multiset继承于JDK的Cllection接口,而不是Set接口. Multiset主要方法介绍: a ...
 - UVA11136Hoax or what( multiset的应用)
		
题目链接 题意:n天,每天往一个箱子里放m个数,放完之后取最大的Max和最小的min做差,并把这两个数去掉,求n天之后的和 multiset 和 set的原理是相似的,multiset可以存多个相同的 ...
 - 4.2 set和multiset
		
使用必须包含头文件set 1)multiset *:定义 如果不给第二个参数,默认less<key>,即用<来进行. 例如: A是一个类的名字,则可以定义一个容器对象如下: mult ...
 - STL(multiset) UVA 11020 Efficient Solutions
		
题目传送门 题意:训练指南P228 分析:照着书上的做法,把点插入后把它后面不占优势的点删除,S.size ()就是优势的人数,时间复杂度O (nlogn) #include <bits/std ...
 - Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset(可持久化Trie)
		
D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input standa ...
 - STL中的set/multiset小结
		
(1)使用set/multiset之前必须包含头文件<set>:#include<set> (2)namespace std{ template <class T, cl ...
 - STL--集和多集(set/multiset)
		
与基本容器相比,关联容器更注重快速和高效地检索数据的能力.这些容器是根据键值(key)来检索数据的,键可以是值也可以是容器中的某一成员.这一类中的成员在初始化后都是按一定顺序排好序的. 本文地址:ht ...
 
随机推荐
- 【读书笔记】iOS-特性
			
一,@符号标志着“你将使用Objective-C的特殊用法”.@property是一种新的编译器功能,表示声明了一个新对象属性. 二,@property预编译指令的作用是自动声明属性的setter和g ...
 - SqlSever大数据分页
			
在sql sever中大数据的分页一直是难以处理的一块,利用id自增列分页也存在不足之处.从一个相对全面的分页看,sql sever2005中新增的row_number()函数解决了这个问题.还是从一 ...
 - iOS 学习 - 1.代理传值
			
代理的目的是改变或传递控制链.允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针.可以减少框架复杂度. 另外一点,代理可以理解为java中的回调监听机制的一种类似 优点:1.避免子类化带 ...
 - java网络---再论URL & URI
			
关于URL 和URI的关系,在本系列的第二篇:java网络---基本web概念 中已经简述了. 这里重复一点,就是URI包含URL,或者说URI是父类,URL就是子类的概念. 本篇再来详述这2个概念. ...
 - OOD沉思录 --- 类和对象的关系 --- 包含关系3
			
4.7 类包含的对象数目不应当超过开发者短期记忆数量,这个数目通常应该是6左右 4.8 让系统在窄而深的包含体系中垂直分布 假设有如下两份菜单: 正餐 --->甜瓜 --->牛排 ---& ...
 - Effective Java 21 Use function objects to represent strategies
			
Theory In the Java the function pointers is implemented by the declaring an interface to represent s ...
 - JavaScript Patterns 4.4 Self-Defining Functions
			
If you create a new function and assign it to the same variable that already holds another function, ...
 - MCS51系列单片机实用技术部分课件
 - hdu 4848 Wow! Such Conquering! (floyd  dfs)
			
Wow! Such Conquering! Problem Description There are n Doge Planets in the Doge Space. The conqueror ...
 - web.xml文件报错:cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'.
			
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" ...