一、set和multiset基础

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

需要包含头文件:

#include <set>

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

  1. template<class _Kty,
  2. class _Pr = less<_Kty>,
  3. class _Alloc = allocator<_Kty> >
  4. class set
template<class _Kty,
class _Pr = less<_Kty>,
class _Alloc = allocator<_Kty> >
class set
  1. template<class _Kty,
  2. class _Pr = less<_Kty>,
  3. class _Alloc = allocator<_Kty> >
  4. class multiset
template<class _Kty,
class _Pr = less<_Kty>,
class _Alloc = allocator<_Kty> >
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参数定义:

  1. set<int,greater<int>> col1;
set<int,greater<int>> col1;

此时,排序准则就是型别的一部分。型别系统确保只有排序准则相同的容器才能被合并。

程序实例:

  1. #include <iostream>
  2. #include <set>
  3. using namespace std;
  4. int main()
  5. {
  6. set<int> s1;
  7. set<int,greater<int> > s2;
  8. for (int i = 1;i < 6;++i)
  9. {
  10. s1.insert(i);
  11. s2.insert(i);
  12. }
  13. if(s1 == s2)
  14. cout << "c1 equals c2 !" << endl;
  15. else
  16. cout << "c1 not equals c2 !" << endl;
  17. }
#include <iostream>
#include <set>
using namespace std; int main()
{
set<int> s1;
set<int,greater<int> > s2; for (int i = 1;i < 6;++i)
{
s1.insert(i);
s2.insert(i);
}
if(s1 == s2)
cout << "c1 equals c2 !" << endl;
else
cout << "c1 not equals c2 !" << endl;
}

程序运行会报错。但是如果把s1的排序准则也指定为greater<int>便运行成功。

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

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

程序实例:

  1. #include <iostream>
  2. #include "print.hpp"
  3. #include <set>
  4. using namespace std;
  5. template <class T>
  6. class RuntimeCmp{
  7. public:
  8. enum cmp_mode{normal,reverse};
  9. private:
  10. cmp_mode mode;
  11. public:
  12. RuntimeCmp(cmp_mode m = normal):mode(m){}
  13. bool operator()(const T &t1,const T &t2)
  14. {
  15. return mode == normal ? t1 < t2 : t2 < t1;
  16. }
  17. bool operator==(const RuntimeCmp &rc)
  18. {
  19. return mode == rc.mode;
  20. }
  21. };
  22. typedef set<int,RuntimeCmp<int> > IntSet;
  23. void fill(IntSet& set);
  24. int main()
  25. {
  26. IntSet set1;
  27. fill(set1);
  28. PRINT_ELEMENTS(set1,"set1:");
  29. RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);
  30. IntSet set2(reverse_order);
  31. fill(set2);
  32. PRINT_ELEMENTS(set2,"set2:");
  33. set1 = set2;//assignment:OK
  34. set1.insert(3);
  35. PRINT_ELEMENTS(set1,"set1:");
  36. 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>
  37. cout << "set1 and set2 have the same sorting criterion" << endl;
  38. else
  39. cout << "set1 and set2 have the different sorting criterion" << endl;
  40. }
  41. void fill(IntSet &set)
  42. {
  43. set.insert(4);
  44. set.insert(7);
  45. set.insert(5);
  46. set.insert(1);
  47. set.insert(6);
  48. set.insert(2);
  49. set.insert(5);
  50. }
#include <iostream>
#include "print.hpp"
#include <set>
using namespace std; template <class T>
class RuntimeCmp{
public:
enum cmp_mode{normal,reverse};
private:
cmp_mode mode;
public:
RuntimeCmp(cmp_mode m = normal):mode(m){} bool operator()(const T &t1,const T &t2)
{
return mode == normal ? t1 < t2 : t2 < t1;
} bool operator==(const RuntimeCmp &rc)
{
return mode == rc.mode;
}
}; typedef set<int,RuntimeCmp<int> > IntSet; void fill(IntSet& set); int main()
{
IntSet set1;
fill(set1);
PRINT_ELEMENTS(set1,"set1:"); RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse); IntSet set2(reverse_order);
fill(set2);
PRINT_ELEMENTS(set2,"set2:"); set1 = set2;//assignment:OK
set1.insert(3);
PRINT_ELEMENTS(set1,"set1:"); if(set1.value_comp() == set2.value_comp())//value_comp Returns the comparison object associated with the container
cout << "set1 and set2 have the same sorting criterion" << endl;
else
cout << "set1 and set2 have the different sorting criterion" << endl;
} void fill(IntSet &set)
{
set.insert(4);
set.insert(7);
set.insert(5);
set.insert(1);
set.insert(6);
set.insert(2);
set.insert(5);
}

运行结果:

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

非变动性操作

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

特殊的搜寻函数

赋值

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

迭代器相关函数

元素的插入和删除

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

set提供的插入函数:

  1. pair<iterator,bool> insert(const value_type& elem);
  2. iterator  insert(iterator pos_hint, const value_type& elem);
pair<iterator,bool> insert(const value_type& elem);
iterator insert(iterator pos_hint, const value_type& elem);

multiset提供的插入函数:

  1. iterator  insert(const value_type& elem);
  2. iterator  insert(iterator pos_hint, const value_type& elem);
iterator  insert(const value_type& elem);
iterator insert(iterator pos_hint, const value_type& elem);

返回值型别不同的原因是set不允许元素重复,而multiset允许。当插入的元素在set中已经包含有同样值的元素时,插入就会失败。所以set的返回值型别是由pair组织起来的两个值:

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

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

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

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

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

  1. iterator erase(iterator pos);
  2. iterator erase(iterator beg, iterator end);
 iterator erase(iterator pos);
iterator erase(iterator beg, iterator end);

关联式容器的erase()函数:

  1. void     erase(iterator pos);
  2. void     erase(iterator beg, iterator end);
 void     erase(iterator pos);
void erase(iterator beg, iterator end);

这完全是为了性能的考虑。因为关联式容器都是由二叉树实现,搜寻某元素并返回后继元素可能很费时。

五、set应用示例:

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

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

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

运行结果:

来源:http://blog.csdn.net/xiajun07061225/article/details/7459206

容器set和multiset的更多相关文章

  1. C++ STL学习之容器set和multiset (补充材料)

    一.set和multiset基础 set和multiset会根据特定的排序准则,自动将元素进行排序.不同的是后者允许元素重复而前者不允许. 需要包含头文件: #include <set> ...

  2. 08--STL关联容器(set/multiset)

    一:set/multiset的简介 set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. set采用红黑树变体的数据结构实 ...

  3. STL标准库-容器-set与multiset

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key se ...

  4. 【C/C++开发】容器set和multiset,C++11对vector成员函数的扩展(cbegin()、cend()、crbegin()、crend()、emplace()、data())

    一.set和multiset基础 set和multiset会根据特定的排序准则,自动将元素进行排序.不同的是后者允许元素重复而前者不允许. 需要包含头文件: #include <set> ...

  5. STL——容器(Set & multiset)的查找

    1. set.find(elem); //查找elem元素,返回指向elem元素的迭代器. 1 #include <iostream> 2 #include <set> 3 4 ...

  6. STL——容器(Set & multiset)之 仿函数(函数对象)functor 的用法

    Set/multiset 中元素的存储数据总是会按照从大到小或者从小到大排列,这个是怎么实现的?这就要说 "仿函数" 这个概念了. 仿函数概念 1. 尽管函数指针被广泛用于实现函数 ...

  7. STL——容器(Set & multiset)编译器提供的16种构造(挖个坑)

    Set & multiset 在vs2019编译器中提供了16种构造方法 1.默认的无参构造 2.比较容器内容,key_comp()函数返回一个比较key的函数. 3.使用迭代器的区间拷贝,拷 ...

  8. STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值

    1. 默认构造 set<int> setInt;              //一个存放int的set容器. set<float> setFloat;          //一 ...

  9. STL——容器(Set & multiset)的概念和特点

    1. Set 和 multiset 的概念 set 和 multiset 是一个集合容器,其中 set 所包含的元素是唯一的,集合中的元素按一定的顺序排列.set 采用红黑树变体的数据结构实现,红黑树 ...

随机推荐

  1. 7:django 中间件

    中间件 中间件是一个连接django请求/相应处理的框架,是一个轻量级的低层次的全局影响django输入输出的系统插件. 每一个中间件组件负责一些特定的功能,这里我们我们只看一下如何激活使用系统自带的 ...

  2. linux命令(32):free命令

    1.显示内存使用情况:free  free –g  free –m 2.以总和的形式显示内存的使用信息: free -t 3.周期性的查询内存使用信息:free -s 10

  3. selenium+python自动化78-autoit参数化与批量上传【转载】

    转至博客:上海-悠悠 前言前一篇autoit实现文件上传打包成.exe可执行文件后,每次只能传固定的那个图片,我们实际测试时候希望传不同的图片.这样每次调用的时候,在命令行里面加一个文件路径的参数就行 ...

  4. MapReduce案例一:天气温度

    1.需求 2.思路 3.代码实现 3.1MyWeather 类代码: 这个类主要是用来定义hadoop的配置,在执行计算程序时所需加载的一些类. package com.hadoop.mr.weath ...

  5. hdu 4240(最大流+最大流量的路)

    Route Redundancy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. aliyun服务器ubuntu系统+MySQL+SqlDeveloper

    首先按照 https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-16-04 https://w ...

  7. head first (三):装饰者模式

    看到别人写的,都看不进去,算了还是自己手写一遍吧,算是帮助自己理解了.写的比较简单,例子也比较好懂,什么时候使用自己看着办. 1.定义 装饰者模式:动态地将职责附加到对象上.若要扩展功能,装饰者提供比 ...

  8. prerender.io 搜索引擎优化 部署成windows服务 实现开机自动开启服务

    一  prerender.io服务端部署 参考官方网站的部署步骤: $ git clone https://github.com/prerender/prerender.git $ cd preren ...

  9. 转:攻击JavaWeb应用[6]-程序架构与代码审计

    转:http://static.hx99.net/static/drops/tips-429.html 攻击JavaWeb应用[6]-程序架构与代码审计 园长 · 2013/08/12 16:53 注 ...

  10. 【我要学python】爬虫准备之了解基本的html标签

    HTML 标题 <h1>This is a heading</h1> HTML 段落 <p>This is a paragraph.</p> HTML ...