set就是数学上的集合——每个元素最多只能出现一次。

【关于set】
set是关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也称为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。

【关联型容器概述】

在学习序列式容器时,我们知道,容器中元素的顺序都是由程序决定的,程序可以随意指定新元素的插入位置,而对于关联型容器,它的所有元素都是经过排序的,关联型容器都是有序的。它的每一个元素都有一个键(key),容器中的元素是按照键的取值升序排列的。
关联型容器内部实现为一个二叉树,在二叉树中,每个元素都有一个父节点和两个子节点。左子树的所有元素都比自己小,右子树的所有元素都比自己大。

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

关联型容器内部结构都是以这种一叉树结构实现, 这也使得它可以高效地查找容器中的每一个元素,但却不能实现任意位置的操作。
标准库提供了四种关联型容器: set(集合)、multiset(多重集合)、map(映射)、multimap(多重映射),其中set与multiset 包含在头文件set中,map与multimap包含在头文件map中。

set与muliset的区别在于是否允许有重复元素,其他用法都很相似,因此将这两种容器放在一起进行讲解, 接下来我们就分 别讲解集合对象的创建及其常用的操作方法。

【set、muliset中常用的方法】
1、创建对象。

set与muliset中都重载了不同的构造函数,因此可以以不同的方式定义集合,set 集合的定义方式如下所示:
set<T> s;          //创建一个空的set集合,默认升序排列
set<T, op> s;        //创建一个空的set集合,按op规则排序
set<T> s(begin, end) ;     //创建一个集合,用[begin, end]区间为其 初始化
set<T,op> s (begin, end) ;    //创建集合,用[begin, end]区间为其初始化并按op规则排序
set<T> s(s1) ;       //创建一个空的set集合,用另一个集合s1初始化

set集合提供了五种重载构造函数,接下来我们分别用这五种方式定义不同的集合,代码
如下所示:
set<char> s1;
set<int, greater<int>()> s2;
set<float> s3(begin, end) ;
set<string,greater<string>()> s4 (begin, end) ;
set<int> s5(s2) ;
注:
geater<T>从大到小
less<T> 从小到大

上述代码分别用不同的方式定义了char、int等类型的集合,其中集合s2与s4中greater<T>则是排序规则,意指从大到小的顺序排列,如果没有排序规则,则默认规则是less<T>,意为从小到大排序,这是STL中定义的函数对象( functor),包含在头文件functional
与set集合一样,multiet也重载了这五种构造函数,接下来用这五种方式分别定史不同的multiset集合对象,代码如下所示:

multiset <char> ms1 ;
multiset <int, greater<int> ()> ms2;
multiset <float>ms3 (begin, end) ;
multiset <string, greater<string>()> ms4 (begin, end) ;
multiset <int> ms5(s2) ;

上述代码分别用五种不同的方式定义了五个multiset 集合对象,其定义中的参数与set集合一样,这里就不再赘述。

2、集合的大小,元素的查找和统计。

s.size();              //返回容器中元素的数目
s.max_size();       //返回容器中可容纳的最大元素数量
s.empty();      //判断容器是否为空

上述函数 调用中的s指集合容器,如无特殊说明,则s既可以是set容器也可以是multiset容器,即两个容器都提供了这样的函数。

s.find();      //查找函数

s.count();      //统计个数的函数

find( )函数的功能是返回key元素的位置,返回值是迭代器类型。count( )函数的功能是返回元素elem的个数,对于set集合来说,要么是0要么是1,而对于multiset来说,值可能大于1。

3、获取头尾部元素。

s.begin();     //返回容器中收元素的位置
s.end();      //返回容器中最后一个元素字后的迭代器

4、插入和删除元素。

s.insert(elem);     //在容器中插入元素elem
s.insert(pos, elem);    //在pos位置插入元素elem
s.insert(begin, end);    //在容器中插入[begin,end]区间的值

对于set容器来说,第一种形式的insert( )调用的返回值是pair<iterator, bool>对象,其第一个参数iterator 是迭代器,指示元素插入的位置;第二个参数bool类型的值代表元素是否插入成功。

这是因为set容器中不允许存在重复的元素,如果要插入一个容器中已存在的元素,则插入操作会失败,而pair中的bool值就是标识插入是否成功,而multiset不存在这样的情况,因此multiset返回的是-个 iterator。

set与multiset提供的erase( )函数也有几种实现形式,其函数调用形式如下所示:

s.erase (pos) ;          //删除pos位置上的元素
s.erase (begin, end) ;    //删除[begin, end) 区间上的元素
s.erase (elem) ;      / /删除元素elem
调用erase()函数可以删除某一个位置 上的元素,可以删除指定的元素,也可以删除指定范围的元素。

5、其他

equal_range() 返回一对定位器,分别表示第一个大于或等于给定关键值的元素和 第一个大于给定关键值的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于end()的值。具体这个有什么用途我还没遇到过~~~
find() ,返回给定值值得定位器,如果没找到则返回end()。
lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回最后一个大于等于key_value的定位器


【示例代码】

 #include <iostream>
#include <set>
#include <functional>
using namespace std;
int main()
{
set<int, greater<int>> s; //创建一个set容器,元素按降序排列
multiset<char> ms; //创建一个multiset容器
cout << "s能容纳的最大元素数量" << s.max_size() << endl;
cout << "ms能容纳的最大元素数量" << ms.max_size() << endl;
//向s中插入元素
pair<set<int>::iterator, bool> ps;
ps = s.insert();
if (ps.second == true)
cout << "insert success" << endl;
s.insert();
s.insert();
s.insert();
//向ms中插入元素
ms.insert('a');
ms.insert('z');
ms.insert('T');
ms.insert('u');
ms.insert('u');
//输出两个容器中的元素
set<int>::iterator its; //创建s容器的迭代器,用于获取元素
cout << "s容器中元素:";
for (its = s.begin(); its != s.end(); its++)
cout << *its << " ";
cout << endl;
multiset<char>::iterator itms; //创建ms容器的迭代器
cout << "ms容器中元素:";
for (itms = ms.begin(); itms != ms.end(); itms++)
cout << *itms << " ";
cout << endl; //查找两个容器中头尾元素
cout << "s头元素: " << *s.begin() << endl;
cout << "ms尾元素: " << *(--ms.end()) << endl;
//查找ms容器中u元素出现的次数
cout << "ms容器中u元素出现的次数:" << ms.count('u') << endl;
system("pause");
return ;
}

运行结果如下

样例中创建了一个set容器s和一个multiset容器ms,其中容器s中的元素是按降序排列,代码9~ 10行调用max_ size( )函数分别算出两个容器的最大容量,代码12~24行分别调用insert( )函数向两个容器中插入元素,其中ms容器中插入了重复的元素u,代码26~35行分别创建相应的迭代器输出容器中的元素,由图8-14可知,s中的元素按降序排列,ms中的元素按升序排列。代码37~ 38行分别调用begin()与end( )函数输出s的头元素和ms的尾元素,由运行结果可知,两个元素输出成功。代码41行调用count( )函数输出ms容器中u元素的个数,由运行结果可知,ms容器中u元素有两个。

最后我们用一到题来体会set的用处。

【问题描述】输入一个文本,找出所有不同的单词(连续的字母序列),按字典序从小到大输出。单词不区分大小写。

【样例输入】

Adventures in Disneyland

Two blondes were going to Disneyland when they came to a fork in the
road. The sign read: "Disneyland Left."

So they went home.

【样例输出】

a
adventures
blondes
came
disneyland
fork
going
home
in
left
read
road
sign
so
the
they
to
two
went
were
when

【代码如下】

 #include<iostream>
#include<string>
#include<set>
#include<sstream>//stringstream要包含的头文件
using namespace std;
set<string> dict;//string 集合 int main()
{ string s, buf;
while (cin >> s)
{
for (int i = ; i < s.length(); i++)
if (isalpha(s[i]))//是否是字母
s[i] = tolower(s[i]);//变成小写
else
s[i] = ' ';
stringstream ss(s);
//stringstream是字符串流。
//它将流与存储在内存中的string对象绑定起来。
//在多种数据类型之间实现自动格式化。
while (ss >> buf)
dict.insert(buf);//插入元素
}
for (set<string>::iterator it = dict.begin(); it != dict.end(); ++it)//循环输出
cout << *it << "\n"; system("pause");
return ;
}

set和muliset的更多相关文章

  1. set && muliset

    #include <set> #include <iostream> #include <cstdio> #include <cctype> using ...

  2. C++实现python标准库中的Counter

    看python standard library by exmple里面提到一个Counter容器,它像muliset一样,能够维持一个集合,并在常量时间插入元素.查询某个元素的个数,而且还提供了一个 ...

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

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

  4. 09--STL关联容器(map/multimap)

    一:map/multimap的简介 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. map中key值是唯一的.集合中的元素按一定的顺 ...

  5. [luogu2286][HNOI2004]宠物收养场【平衡树】

    [传送门] 前言 这一篇题解并不是为了讲什么算法,只是总结一下平衡树在OI考试中的注意事项. 题意简化(给不想看题目的小伙伴们一点福利) 给你两堆数,每一次给你一个数,每一次在另外一堆数中找到这个数的 ...

  6. bzoj1058: [ZJOI2007]报表统计 stl xjbg

    小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一.经过仔细观察,小Q发现统计一张报表实际上是维护一个可能为负数的整数数列,并且 ...

  7. 2017-10-28-afternoon-清北模拟赛

    T1 水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌 ...

  8. Hoax or what UVA - 11136(multiset的应用)

    刚开始把题意理解错了,结果样例没过,后来发现每天只处理最大和最小的,其余的不管,也就是说昨天的元素会影响今天的最大值和最小值,如果模拟的话明显会超时,故用multiset,另外发现rbegin()的功 ...

  9. Couleur(启发式 + 主席树)(终于补坑了)

    ZOJ Problem Set - 4053 Couleur Time Limit: 6 Seconds      Memory Limit: 131072 KB DreamGrid has an a ...

随机推荐

  1. (转)hive调优(1) coding调优

    hive 调优(一)coding调优 本人认为hive是很好的工具,目前支持mr,tez,spark执行引擎,有些大公司原来封装的sparksql,开发py脚本,但是目前hive支持spark引擎(不 ...

  2. TCP/IP 这猝不及防的爱情

    前言 前几天看了老刘的一篇文章,TCP/IP 大明邮差.正好最近也在读<计算机自顶向下>一书 心血来潮,想写一个女版的TCP/IP 正文 一天,我正在百花会上赏花,赏着赏着,就出现了一个令 ...

  3. oracle利用触发器实现主键字段自增

    我们都知道oracle主键自增利用的是序列sequence.我们先创建一个sequence: create sequence test_sequence start increment maxvalu ...

  4. 【转载】 迁移学习与fine-tuning有什么区别

    原文地址: https://www.cnblogs.com/fangpengchengbupter/p/8276204.html ----------------------------------- ...

  5. ISO/IEC 9899:2011 条款6.4.3——通用字符名

    6.4.3 通用字符名 语法 1.通用字符名: universal_character-name: \u hex-quad(四位十六进制数) \U hex-quad hex-quad hex-quad ...

  6. DisplayAttribute应用——根据PropertyName自动获取对应的UI显示名

    model定义,使用DisplayAttribute public class AddressSetInfo { /// <summary> /// invoiceAddress.Id / ...

  7. svn add 命令 递归目录下所有文件

    svn add 命令 递归目录下所有文件 摘自:https://blog.csdn.net/yefl007/article/details/46506281 即使被忽略了也可以使用此命令. svn a ...

  8. vue.js 同级组件之间的值传递方法(uni-app通用)

    vue.js 兄弟组件之间的值传递方法 https://blog.csdn.net/jingtian678/article/details/81634149

  9. jQuery BlockUI Plugin Demo 3(Page Blocking Examples)

    This page demonstrates several ways to block the page. Each button below activates blockUI and then ...

  10. react中如何处理日期格式整理

    1.第一种模式——对应组件:DatePicker: 需要引入 import moment from "moment"; values.cfjdrq = moment(values. ...