STL Set和multiset 容器

set/multiset的简介

set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。 元素插入过程是按排序规则插入,所以不能指定插入位置。
        set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操 作上比vector快。
        set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
        multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset 中同一值可以出现多次。
        不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果
        希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
        #include <set>

红黑树模型:

set/multiset对象的默认构造

set默认构造函数:set<T> st
multiset默认构造函数: mulitset<T> mst

示例:

set<int> setInt;
//一个存放int的set容器。

set<float> setFloat;
//一个存放float的set容器。

set<string> setString;
//一个存放string的set容器。

multiset<int> mulsetInt;
//一个存放int的multi set容器。

multi set<float> multisetFloat;
//一个存放float的multi set容器。

multi set<string> multisetString;
//一个存放string的multi set容器。

set对象的拷贝构造与赋值

理论知识:

set(const set &st);
拷贝构造函数

set& operator=(const set &st)
重载等号操作符

set.swap(st)
交换两个集合容器

示例:

set<int> setIntA;
setIntA.insert(3);
setIntA.insert(1);
setIntA.insert(7);
setIntA.insert(5);
setIntA.insert(9);
set<int> setIntB(setIntA); //1 3 5 7 9
set<int> setIntC;
setIntC = setIntA; //1 3 5 7 9
setIntC.insert(6);
setIntC.swap(setIntA); //交换

set的大小

理论知识:

set.size()
返回容器中元素的数目

set.empty()
判断容器是否为空

示例:

set<int> setIntA;
setIntA.insert(3);
setIntA.insert(1);
setIntA.insert(7);
setIntA.insert(5);
setIntA.insert(9);

if (!setIntA.empty())
{
int iSize = setIntA.size(); //5
}

set的插入与迭代器

理论知识:

set.insert(elem)
在容器中插入元素。

set.begin()
返回容器中第一个数据的迭代器。

set.end()
返回容器中最后一个数据之后的迭代器

set.rbegin()
返回容器中倒数第一个元素的迭代器。

set.rend()
返回容器中倒数最后一个元素的后面的迭代器。

示例:

set<int> setInt;
setInt.insert(3);
setInt.insert(1);
setInt.insert(5);
setInt.insert(2);

for(set<int>::iterator it=setInt.begin(); it!=setInt.end(); ++it)
{
int iItem = *it;
cout << iItem; //或直接使用
cout << *it
}
//这样子便顺序输出 1 2 3 5。

set.rbegin()与set.rend()。略。

set的删除

理论知识:

set.clear()
清除所有元素

set.erase(pos)
删除pos迭代器所指的元素,返回下一个元素的迭代器。

set.erase(beg,end)
删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。

set.erase(elem)
删除容器中值为elem的元素。

示例:

删除区间内的元素

setInt是用set<int>声明的容器,现已包含按顺序的1,3,5,6,9,11元素。
set<int>::iterator itBegin=setInt.begin();
++ itBegin;
set<int>::iterator itEnd=setInt.begin();
++ itEnd;
++ itEnd;
++ itEnd;
setInt.erase(itBegin,itEnd);
//此时容器setInt包含按顺序的1,6,9,11四个元素。

删除容器中第一个元素
setInt.erase(setInt.begin()); //6,9,11

删除容器中值为9的元素
set.erase(9);

删除setInt的所有元素
setInt.clear(); //容器为空

Set集合的元素排序

set<int,less<int> > setIntA; //该容器是按升序方式排列元素。
        set<int,greater<int>> setIntB; //该容器是按降序方式排列元素。
        set<int> 相当于 set<int,less<int>>。
         less<int>与greater<int>中的int可以改成其它类型,该类型主要要跟set容纳的数据 类型一致。
         疑问1:less<>与greater<>是什么?
        疑问2:如果set<>不包含int类型,而是包含自定义类型,set容器如何排序?
         要解决如上两个问题,需要了解容器的函数对象,也叫伪函数,英文名叫functor。
        下面将讲解什么是functor,functor的用法。

示例:

使用stl提供的函数对象

set<int,greater<int>> setIntB;
setIntB.insert(3);
setIntB.insert(1);
setIntB.insert(5);
setIntB.insert(2);
此时容器setIntB就包含了按顺序的5,3,2,1元素

函数对象functor的用法

尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数 的方法,那就是函数对象。 
         functor,翻译成函数对象,伪函数,运算符是重载了“()”操作符的普通类对象。从 语法上讲,它与普通函数行为类似
         greater<>与less<>就是函数对象。
         下面举出greater<int>的简易实现原理。

示例:
下面举出greater<int>的简易实现原理。
struct greater
{
         bool operator()(const int& iLeft, const int& iRight)
         {
                  //如果是实现less<int>的话,这边是写return (iLeft<iRight);
                  return (iLeft>iRight);
         }
}

容器就是调用函数对象的operator()方法去比较两个值的大小。

题目:学生包含学号,姓名属性,现要求任意插入几个学生对象到set容器中,使得容器中的学生按学号的升序排序。

解:
//学生类
class CStudent
{
public:
         CStudent(int iID, string strName)
         {
                  m_iID = iID;
                  m_strName = strName;
         }
         int m_iID;
         //学号
         string m_strName;
         //姓名
}
//为保持主题鲜明,本类不写拷贝构造函数,本类也不需要写拷贝构造函数。但大家仍要有考虑拷贝构造函数的习惯。

//函数对象
struct
StuFunctor
{
         bool operator() (const CStudent &stu1, const CStudent &stu2)
         {
                  return (stu1.m_iID<stu2.m_iID);
         }
}

//main函数
void main()
{
         set<CStudent, StuFunctor>
         setStu;
         setStu.insert(CStudent(3,"小张"));
         setStu.insert(CStudent(1,"小李"));
         setStu.insert(CStudent(5,"小王"));
         setStu.insert(CStudent(2,"小刘")); //此时容器setStu包含了四个学生对象,分别是按姓名顺序的“小李”,“小刘”,“小张”,“小王”
}

set的查找

set.find(elem); //查找elem元素,返回指向elem元素的迭代器。 
       set.count(elem); //返回容器中值为elem的元素个数。对set来说,要么是0,要 么是1。对multiset来说,值可能大于1。
       set.lower_bound(elem); //返回第一个>=elem元素的迭代器。 
       set.upper_bound(elem); // 返回第一个>elem元素的迭代器。 
       set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上 限是闭区间,下限是开区间,如[beg,end)。 
       以上函数返回两个迭代器,而这两个迭代器被封装在pair中。 
       以下讲解pair的含义与使用方法。

示例:
set<int> setInt;
setInt.insert(3);
setInt.insert(1);
setInt.insert(7);
setInt.insert(5);
setInt.insert(9);

set<int>::iterator itA = setInt.find(5);
int iA = *itA; //iA == 5
int iCount = setInt.count(5); //iCount == 1
set<int>::iterator itB = setInt.lower_bound(5);
set<int>::iterator itC = setInt.upper_bound(5);
int iB = *itB; //iB == 5
int iC = *itC; //iC == 7

pair< set<int>::iterator, set<int>::iterator > pairIt = setInt.equal_range(5); //pair是什么?

pair的使用

pair译为对组,可以将两个值视为一个单元。
        pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可 以是自定义类型。
        pair.first是pair里面的第一个值,是T1类型。
        pair.second是pair里面的第二个值,是T2类型。

示例:
set<int> setInt;
... //往setInt容器插入元素1,3,5,7,9

pair< set<int>::iterator , set<int>::iterator > pairIt = setInt.equal_range(5);
set<int>::iterator itBeg = pairIt.first;
set<int>::iterator itEnd = pairIt.second;
//此时 *itBeg==5 而 *itEnd == 7

小结

一、容器set/multiset的使用方法; 红黑树的变体,查找效率高,插入不能指定位置,插入时自动排序。

二、functor的使用方法; 类似于函数的功能,可用来自定义一些规则,如元素比较规则。

三、pair的使用方法。 对组,一个整体的单元,存放两个类型(T1,T2,T1可与T2一样)的两个元素。

案例:

int x;
scanf("%ld",&x);
multiset<int> h;//建立一个multiset类型,变量名是h,h序列里面存的是int类型,初始h为空
while(x!=0){
        h.insert(x);//将x插入h中
        scanf("%ld",&x);
}
pair< multiset<int>::iterator , multiset<int>::iterator > pairIt = h.equal_range(22);
multiset<int>::iterator itBeg = pairIt.first;
multiset<int>::iterator itEnd = pairIt.second;
int nBeg = *itBeg;
int nEnd = *itEnd;
while(!h.empty())
{// 序列非空h.empty()==true时表示h已经空了
        multiset<int>::iterator c = h.begin();//c指向h序列中第一个元素的地址,第一个元素是最小的元素
        printf("%ld ",*c);//将地址c存的数据输出
        h.erase(c);//从h序列中将c指向的元素删除
}

STL Set和multiset 容器的更多相关文章

  1. STL之Set和multiset容器

    1.Set和multiset容器 1)set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指定插入位置. 2)set采用红黑树变体的数据 ...

  2. C++ STL 学习笔记__(7)Set和multiset容器

    10.2.8 Set和multiset容器 set/multiset的简介 ²  set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列.元素插入过程是按排序规则插入,所以不能指 ...

  3. 详解C++ STL multiset 容器

    详解C++ STL multiset 容器 本篇随笔简单介绍一下\(C++STL\)中\(multiset\)容器的使用方法及常见使用技巧. multiset容器的概念和性质 \(set\)在英文中的 ...

  4. STL学习系列八:Set和multiset容器

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

  5. stl之multiset容器的应用

    与set集合容器一样,multiset多重集合容器也使用红黑树组织元素数据,仅仅是multiset容器同意将反复的元素健值插入.而set容器则不同意. set容器所使用的C++标准头文件set.事实上 ...

  6. 2.8 C++STL set/multiset容器详解

    文章目录 2.8.1 引入 2.8.2 代码示例 2.8.3 代码运行结果 2.8.4 对组pair的补充 代码实例 运行结果 总结 2.8.1 引入 set/multiset容器概念 set和mul ...

  7. STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  8. 【转】 STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  9. STL中的set容器的一点总结(转)

    STL中的set容器的一点总结 1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂 ...

随机推荐

  1. python simple factory mode example

    Two python simple factory mode examples shown in this section. One is for base operation and another ...

  2. bootstrap switch样式修改与多列等间距布局

    先以一张图开启今天的随笔 今天实习遇到了switch按钮,小姐姐说用插件bootstrap switch来写,我第一次用这个插件,首先在引入方面就遇到了很多坑,先来总结一下bootstrap swit ...

  3. docker server gave HTTP response to HTTPS client 问题处理办法

    vi /etc/docker/daemon.json [root@localhost ~]# cat /etc/docker/daemon.json {"insecure-registrie ...

  4. Python 夺大满贯!三大编程语言榜即将全部“失守”!

    有互联网创业者说: 2019年可能会是过去十年里最差的一年 但却是未来十年里最好的一年 真的是这样吗? “每月工资1w,如何赚到200w?” 同样一个问题,问不同的人会得到不同的答案. 有一类人,开始 ...

  5. Redis的C语言客户端(hiredis)的安装和使用

    关键词:hiredis, cRedis, redis clients, redis客户端, C客户端, 华为云分布式缓存服务 hiredis是一个非常全面的C语言版redis接口库,支持所有命令.管道 ...

  6. Linux加密到K8S中

    文件名字 test.conf 加密:  base64 --wrap=0 aaa.conf 把得到的密钥填入配置文件当中即可

  7. <React Native移动开发实战>-1-React Native的JSX解决方案

    JSX并不是一门新的开发语言,而是Facebook提出的语法方案:一种可以在JavaScript代码中直接书写HTML标签的语法糖,所以,JSX本质上还是JavaScript语言. 小知识:语法糖(S ...

  8. wifi,Android渗透之arp欺骗

    查看自己wifi ip段 查看有哪些用户连接了此wifi,下图标记处为我的测试机(华为) 攻击开始,如果开启了arp防火墙,就会有提示 开启图片捕获

  9. scrapy笔记集合

    细读http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html 目录 Scrapy介绍 安装 基本命令 项目结构以及爬虫应用介绍 简单使用示例 选 ...

  10. Fifteen scrum meeting 2015-11-21

    最近几日因为其他作业着实拖延了很久更新工程进度. 闫昊: 完成:学习讨论区开发 即将进行:讨论区代码开发 唐彬: 完成:学习学习进度部分开发 即将进行:学习进度功能开发 史烨轩: 完成:学习下载功能设 ...