1、set的基础知识

  set的特性是:所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值

  set的各成员函数列表如下:

1. begin():返回指向第一个元素的迭代器;end():返回指向最后一个元素的迭代器;

2.empty():如果集合为空,返回true;clear():清除所有元素;

3. erase():删除集合中的元素

  • erase(iterator) :删除定位器iterator指向的值
  • erase(first,second):删除定位器first和second之间的值
  • erase(key_value):删除键值key_value的值

4. count():返回某个值元素的个数,0或1;

5. find():返回一个指向被查找到元素的迭代器,如果没找到则返回end()。

6. insert():在集合中插入元素,插入函数的返回值不完全相同。

  • insert(key_value);将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
  • inset(first,second);将定位器first到second之间的元素插入到set中,返回值是void.
  • 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);

  返回值型别不同的原因是set不允许元素重复,而multiset允许。当插入的元素在set中已经包含有同样值的元素时,插入就会失败。所以set的返回值型别是由pair组织起来的两个值:第一个元素返回新元素的位置,或返回现存的同值元素的位置。第二个元素表示插入是否成功。

  set的第二个insert函数,如果插入失败,就只返回重复元素的位置!但是,所有拥有位置提示参数的插入函数的返回值型别是相同的。这样就确保了至少有了一个通用型的插入函数,在各种容器中有共通接口。

7. lower_bound(key_value):返回第一个大于等于key_value的定位器;upper_bound(key_value),返回最后一个大于key_value的定位器

8. size():集合中元素的数目;

9. max_size():返回集合能容纳的元素的最大限值

10. swap():交换两个集合变量,比如:c1.swap(c2);   swap(c1, c2);

11. rbegin():返回指向集合中最后一个元素的反向迭代器.; rend():返回指向集合中第一个元素的反向迭代器

12. equal_range()--返回集合中与给定值相等的上下限的两个迭代器

13. get_allocator()--返回集合的分配器

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

15. upper_bound()--返回大于某个值元素的迭代器

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

反向迭代器:set<int>::reverse_iterator

  关于set有下面几个问题:

(1)为何map和set的插入删除效率比用其他序列容器高?

  大部分人说,很简单,因为对于关联容器来说,不需要做内存拷贝和内存移动。说对了,确实如此。set容器内所有元素都是以节点的方式来存储,其节点结构和链表差不多,指向父节点和子节点。结构图可能如下:

  A
   / \
  B C
 / \ / \
  D E F G

因此插入的时候只需要稍做变换,把节点的指针指向新的节点就可以了。删除的时候类似,稍做变换后把指向删除节点的指针指向其他节点也OK了。这里的一切操作就是指针换来换去,和内存移动没有关系。

(2)为何每次insert之后,以前保存的iterator不会失效?

  iterator这里就相当于指向节点的指针,内存没有变,指向内存的指针怎么会失效呢(当然被删除的那个元素本身已经失效了)。相对于vector来说,每一次删除和插入,指针都有可能失效,调用push_back在尾部插入也是如此。因为为了保证内部数据的连续存放,iterator指向的那块内存在删除和插入过程中可能已经被其他内存覆盖或者内存已经被释放了。即使时push_back的时候,容器内部空间可能不够,需要一块新的更大的内存,只有把以前的内存释放,申请新的更大的内存,复制已有的数据元素到新的内存,最后把需要插入的元素放到最后,那么以前的内存指针自然就不可用了。特别时在和find等算法在一起使用的时候,牢记这个原则:不要使用过期的iterator。

(3)当数据元素增多时,set的插入和搜索速度变化如何?

  如果你知道log2的关系你应该就彻底了解这个答案。在set中查找是使用二分查找,也就是说,如果有16个元素,最多需要比较4次就能找到结果,有32个元素,最多比较5次。那么有10000个呢?最多比较的次数为log10000,最多为14次,如果是20000个元素呢?最多不过15次。看见了吧,当数据量增大一倍的时候,搜索次数只不过多了1次,多了1/14的搜索时间而已。你明白这个道理后,就可以安心往里面放入元素了。

  还要注意begin() 和 end()函数是不检查set是否为空的,使用前最好使用empty()检验一下set是否为空.

(4)set和multiset通常以红黑树完成,存在的优缺点?

  和所有关联式容器类似,通常使用平衡二叉树完成。事实上,set和multiset通常以红黑树实作而成。自动排序的优点是使得搜寻元素时具有良好的性能,具有对数时间复杂度。但是造成的一个缺点就是:

  • 不能直接改变元素值。因为这样会打乱原有的顺序。
  • 改变元素值的方法是:先删除旧元素,再插入新元素。
  • 存取元素只能通过迭代器,从迭代器的角度看,元素值是常数。

 2、set 比较函数、自定义比较函数

  比较函数:

   set<int> seta;               //默认是按升序方式排列元素
set<int, less<int>> setA; //按升序方式排列元素 //C++ “greater”: 未声明的标识符错误
//解决方案:在头文件中加入#include<functional>即可解决
set<int, greater<int>> setB; //按降序方式排列元素

  自定义比较函数
    (1)元素不是结构体:
        例:
        //自定义比较函数myComp,重载“()”操作符

  1. struct myComp
  2. {
  3. bool operator()(const your_type &a,const your_type &b)
  4. [
  5. return a.data-b.data>0;
  6. }
  7. }
  8. set<int,myComp>s;
  9. ......
  10. set<int,myComp>::iterator it;
#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <set>
using namespace std; class Student
{
public:
Student(char *name, int age)
{
strcpy(this->name, name);
this->age = age;
}
public:
char name[];
int age;
};
// 仿函数
struct FuncStu
{
bool operator()(const Student &left, const Student &right)
{
return (left.age < right.age);
}
};
int main()
{
Student s1("s1", );
Student s2("s1", );
Student s3("s1", ); set<Student, FuncStu> set1;
set1.insert(s1);
set1.insert(s2);
set1.insert(s3); set<Student, FuncStu>::iterator it;
for (it = set1.begin(); it != set1.end(); ++it)
{
cout << it->age << " " << it->name << endl;
} system("pause");
return ;
}

(2)如果元素是结构体,可以直接将比较函数写在结构体内。
        例:

    1. struct Info
    2. {
    3. string name;
    4. float score;
    5. //重载“<”操作符,自定义排序规则
    6. bool operator < (const Info &a) const
    7. {
    8. //按score从大到小排列
    9. return a.score<score;
    10. }
    11. }
    12. set<Info> s;
    13. ......
    14. set<Info>::iterator it;

参考博客:https://blog.csdn.net/xiajun07061225/article/details/7459206

    https://www.cnblogs.com/ChinaHook/p/6985444.html#top

C++(四十九) — set、multiset 容器的基本操作的更多相关文章

  1. C++(四十八) — string容器的基本操作

    参考博客:https://blog.csdn.net/qq_37941471/article/details/82107077 https://www.cnblogs.com/danielStudy/ ...

  2. Gradle 1.12用户指南翻译——第四十九章. Build Dashboard 插件

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  3. SQL注入之Sqli-labs系列第四十七关,第四十八关,第四十九关(ORDER BY注入)

    0x1 源码区别点 将id变为字符型:$sql = "SELECT * FROM users ORDER BY '$id'"; 0x2实例测试 (1)and rand相结合的方式 ...

  4. “全栈2019”Java第四十九章:重载与重写对比详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. 第四十九个知识点:描述在IPsec和TLS后的基本想法

    第四十九个知识点:描述在IPsec和TLS后的基本想法 网络安全协议(Internet Protocol Security,IPsec)和安全传输层协议(Transport Layer Securit ...

  6. abp(net core)+easyui+efcore实现仓储管理系统——出库管理之一(四十九)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  7. Android项目实战(四十九):Andoird 7.0+相机适配

    解决方案类似: Android项目实战(四十):Andoird 7.0+ 安装APK适配 解决方法: 一.在AndroidManifest.xml 文件中添加 四大组件之一的 <provider ...

  8. Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装

    MonoBehaviourSimplify 中的消息策略完善 在上一篇,笔者说,MonoBehaviourSimplify 中的消息策略还有一些小问题.我们在这篇试着解决一下. 先贴出来代码: usi ...

  9. (四十九)c#Winform自定义控件-下拉框(表格)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

随机推荐

  1. 安装 python 爬虫框架 Scrapy

    官方安装说明文档:https://doc.scrapy.org/en/latest/intro/install.html#installing-scrapy 一.scrapy 需要以下依赖 二.一般来 ...

  2. java导出pdf功能记录

    这几天已在做处理导出pdf文件的功能,摸索了几天总算可以了.记录下这几天遇到的问题. 1.网上基本都是基于Itext5和Itext7来处理的.我最终是在Itext5上成功了,itext7应该是模板出问 ...

  3. CentOS 7上重新编译安装nginx

    CentOS 7的源所提供的nginx几乎不包含任何扩展模块:为了能够使用一些扩展模块,我们需要从源代码重新编译安装nginx. 目前最新版的源代码是1.6.1.下载解压后先不要急着configure ...

  4. 实现简单的string类

    摘要 实现了一个string类,包括基本的构造.赋值.判断.大小写等. String API Constructors string(); string(const char& ch); st ...

  5. jquery如何生成图片验证码

    jQuery(function($){ /**生成一个随机数**/ function randomNum(min, max) { return Math.floor(Math.random() * ( ...

  6. sqlserver 数据类型 C# clr 数据类型 映射

    https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql/linq/sql-clr-type-mapping#default- ...

  7. nginx+upsync+consul 构建动态nginx配置系统

    参考: http://www.php230.com/weixin1456193048.html  [upsync模块说明.性能评测] https://www.jianshu.com/p/76352ef ...

  8. Three.js场景的基本组件

    1.场景Scene THREE.Scene被称为场景图,可以用来保存所有图形场景的必要信息.每个添加到Scene的对象,包括Scene自身都继承自名为THREE.Object3D对象.Scene不仅仅 ...

  9. Delphi阿里云对象存储OSS【支持上传文件、下载文件、删除文件、创建目录、删除目录、Bucket操作等】

    作者QQ:(648437169) 点击下载➨Delphi阿里云对象存储OSS             阿里云api文档 [Delphi阿里云对象存储OSS]支持 获取Bucket列表.设置Bucket ...

  10. 读文件时出现这个错误 'utf-8' codec can't decode byte 0xba in position 21: invalid start byte

    ''' file2 文件内容: 很任性wheniwasyoung ''' 源代码: f = open("file2",'r',encoding="utf-8") ...