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. swoole实验版聊天室

    “swoole实验版聊天室”是依据一堂swoole培训课内容改编的,结合了bootstrap前端框架.redis数据库.jquery框架等实现基本功能,只是体现了swoole的应用,并不是为了专门写个 ...

  2. hibernate 注解大全

    2019年5月1日21:39:55 原文:http://docs.jboss.org/hibernate/orm/5.4/javadocs/ 这个是hibernate 5.4版本 基于hibernat ...

  3. 【MongoDB学习之六】MongoDB集群

    环境 MongoDB 4.0 CentOS 6.5_x64 一.主从复制-Master-Slave这种模式已不再推荐使用了. 二.副本集-Replica Set(用的多)副本集其实一种互为主从的关系, ...

  4. 【Maven学习】定制库到Maven本地资源库

    目标:手工操作将一个jar安装到本地仓库 第一步:首先获取到jar包,可以是第三方的 也可以是自己创建的,放到本地任意目录 比如:joda-time-2.10.3,放到C:\jar\  目录下面 第二 ...

  5. c#实现定时任务(Timer)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. prototype和__proto__的关系是什么?

    我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法.(这个对象下面有个属性,这个属性是另外一个对象的应用 ,这个属性就 ...

  7. jquery预加载显示百分比

    jquery预加载显示百分比 <pre> <img class="bj loadimg" loadimg="/weiqingshu/images/1/b ...

  8. C语言词法分析中的贪心算法

    C语言词法分析中的贪心算法 当我们写出a---b这种语句的时候我们应该考虑C语言的编译器是如何去分析这条语句的. C语言对于解决这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多 ...

  9. cloudera cdh6.3 离线安装 经典大数据平台视频教程(含网盘下载地址)

    cdh6.3企业级大数据视频教程 链接:https://pan.baidu.com/s/1bLGrIwzpFQB-pQRb6KOmNg 提取码:i8h8 系统和软件版本1,操作系统:Centos7.6 ...

  10. 【LEETCODE】73、根据身高重建队列 第406题

    说实话,这道题我没想出来,但是看解题报告题解比较让人觉得眼前一亮,这里记录下来 package y2019.Algorithm.greedy.medium; import java.util.Arra ...