14C++复习.SLT容器之关联式容器(set/multiset/map/multimap)
一、简介
关联容器在存储时是以关键字key为下标进行存储的,标准的STL关联容器分为set和map两大类,之后的衍生版本有multiset和multimap,它们的区别是在存储时是否容许出现关键字key相同的情况。这些容器的底层机制均以RB-tree(红黑树)完成。
1、对组pair类型提供的操作
对组pair包含两个数据值。具体的使用方法如下:
创建一个空的pair对象,它的两个元素分别是T1和T2类型,采用值初始化。
创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。
以v1和v2值创建一个新的pair对象,其元素的类型分别是v1和v2的类型。
两个pair对象之间的小于运算,其定义遵循字典次序:如果p1.first < p2.first或者!(p2.first<p1.first) && p1.second < p2.second,返回true。
如果两个pair对象的first成员和second成员依次相等,则这两个对象相等,该运算使用其元素的==操作符。
p.first、p.second;
返回p中名为first、second的公有数据成员。
2、pair的创建和初始化
在创建pair对象时,必须提供两个类型名,pair对象的两个数据成员各自对应一个,这两个类型名可以不同。如果在创建pair对象时不提供显示初始化,则调用默认构造函数对其成员进行初始化;也可以在创建对象时使用( )直接显示初始化式:
如果使用多个相同的pair对象,也可以使用typedef简化其声明:
Author 对象名(初始值1,初始值2);
对于pair类可以直接访问其数据成员,其成员都是公有的,分别命名为first成员和second成员,使用点操作符即可访问。
3、set和map
一般来说,关联式容器的内部结构是一个平衡二叉树,以便获得良好的搜寻效率,平衡二叉树有很多种类型,包括AVL-tree,RB-tree等,最被广泛使用的是RB-tree。
(1) 搜索二叉树,因为它的查找平均性能是O(lgN),因此查询中多用这种结构,但如果建立搜索二叉树的时候数据不够随机,可能会导致这棵二叉树出现“左重右轻“之类的失衡情况,这个时候平衡二叉树便体现出它的作用了。
(2)所谓的树形平衡与否,并没有一个绝对的测量标准,大致意义是没有任何一个节点过深。AVL树中定义是任何节点的左右子树高度相差最多为1,在插入新的元素的时候,可能会导致这棵AVL树失去平衡,这个时候就需要用到”单旋转”和“双旋转”两种操作来调节AVL树使之重新平衡。
(3)RB-tree是另一种二叉平衡树,它对“平衡”的定义更弱,它的规则如下:
A. 每个节点不是红色就是黑色
B. 根节点为黑色
C. 如果节点为红色,那么它的子节点必须为黑色
D. 任一节点至NULL的任何路径中,所含的黑色节点数必须相同
所以对于RB-tree的插入和删除是一个很复杂的过程,其中,插入有3中情况,删除有4中情况,但是它能很好地保证查询的效率,通常来说,比其他的平衡二叉树提高25%。
在RB-tree中,有两个函数很重要,一个是pair<iterator,bool> insert_unique(const Value_type &x),这个是将x插入到红黑树中,并且保持节点的独一无二(通常来说,如果使用insert函数在map插入新的元素,如果是重复元素,则不会真正插入,而是直接返回),返回值是一个pair类型,bool标志插入是否成功,iterator根据插入是否成功则指向新插入的节点或者NULL,另外一个是pair<iterator,bool> insert_equal(constValue_type &x),这个函数再插入节点时允许节点关键字key重复,这便是multiset和multimap实现的关键了,这也是它们和set及map最大的区别了。
二、set
1、set/multiset
(1)所有元素都会根据元素的键值自动排列,set的键值就是实值,并且set不允许两个元素相同的键值。
(2)不能通过set的迭代器改变set的元素值,因为set的元素值就是键值,因此这关系到排列规则,如果我们擅自修改元素值,会破坏set内部的排列规则。也正因为这样,STL的set的迭代器是const_iterator。
(3)STL集合的底层结构是红黑树。因此掌握了红黑树的基本操作,那么学习集合set将会很容易,几乎set的所有操作都是转调用红黑树的操作而已。
(4)set内的相同数值的元素只能出现一次,multiset内可包含多个数值相同的元素。
【示例】
#include <set>//用set和multiset前,必须包含头文件<set>
using namespace std;
int main()
{
//type of the collection
typedef set<int> IntSet;
IntSet coll;//set container for int values
//不能够用push_back()因为是自动排序
coll.insert(1);
coll.insert(6);
coll.insert(2);
IntSet::const_iterator pos;
for(pos = coll.begin(); pos != coll.end(); pos++)
cout << *pos << " ";
cout << endl;
return 0;
}
2、map/multimap
(1)map的元素是成对的键值/实值,内部的元素依据其值自动排序;
(2)map内的相同数值的元素只能出现一次,multimap内可包含多个数值相同的元素。
(3)STL集合的底层结构是红黑树。因此掌握了红黑树的基本操作,那么学习集合set将会很容易,几乎set的所有操作都是转调用红黑树的操作而已。
【示例】
//用map/multimap前,必须包含头文件<map>
#include <map>
#include <string>
using namespace std;
int main()
{
//type of the collection
typedef multimap<int, string> intStringMMap;
intStringMMap coll;//container for int/string
//make_pair()便捷函数,返回一个pair对象:pir(first, second)
coll.insert(make_pair(6, "strings"));
coll.insert(make_pair(1, "is"));
coll.insert(make_pair(3, "multimap"));
intStringMMap::iterator pos;
for(pos = coll.begin(); pos != coll.end(); pos++)
{
cout << pos->first << " " << pos->second << endl;;
}
cout << endl;
return 0;
}
转自https://blog.csdn.net/sinat_33924041/article/details/83687024
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!