STL中的部分容器,比如:vector、list、deque、 forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?
关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的键值对,在数据检索时比序列式容器效率更高
键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代 表键值,value表示与key对应的信息
STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层,容器中的元素是一个有序的序列
set是按照特定顺序存储唯一元素的容器
set中的每个元素不可以重复,也不可以更改(为const),但是可以在容器中增加和删除
在内部,set中的元素始终按照其内部比较对象(类型为 Compare)指示的特定严格弱排序标准按其键排序
set的主要功能是排序+去重
set通常用二叉搜索树实现
1.与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放 value,但在底层实际存放的是由构成的键值对
2.set中插入元素时,只需要插入value即可,不需要构造键值对
3.在set中查找一个特定元素的时间复杂度为log2(N),即二分查找
函数名称 | 功能说明 |
empty() | 检验set是否为空 |
size() | 返回容器大小 |
max_size() | 返回容器最大容量 |
函数名称 | 功能说明 |
insert() | 默认尾插数据,如果数据已存在会返回现有元素迭代器 |
erase() | 删除数据 |
find() | 查找数据,返回数据迭代器 |
clear() | 清空set容器 |
count() | 对特定数值进行计数 |
#include
#include
using namespace std;
void test_1()
{
cout << "test_1" << endl;
set s1;
s1.insert(1);
s1.insert(2);
s1.insert(3);
s1.insert(1);
s1.insert(4);
s1.insert(5);
s1.insert(5);
for (auto num : s1)
{
cout << num << " ";
}
cout << endl;
}
void test_2()
{
cout << "test_2" << endl;
set s2;
s2.insert(2);
s2.insert(4);
s2.insert(6);
s2.insert(0);
s2.insert(1);
auto it = s2.begin();
auto end = s2.end();
while (it != end)
{
cout << *it << " ";
it++;
}
cout << endl;
set::reverse_iterator rit = s2.rbegin();
set::reverse_iterator rend = s2.rend();
while (rit != rend)
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
void test_3()
{
cout << "test_3" << endl;
set s3;
s3.insert(2);
s3.insert(4);
s3.insert(6);
s3.insert(0);
s3.insert(1);
int x;
while (cin >> x)
{
auto ret = s3.find(x);
if (ret != s3.end())
{
cout << "在" << endl;
}
else
{
cout << "不在" << endl;
}
}
}
void test_4()
{
cout << "test_4" << endl;
multiset ms1;
ms1.insert(2);
ms1.insert(4);
ms1.insert(6);
ms1.insert(0);
ms1.insert(1);
ms1.insert(1);
ms1.insert(2);
ms1.insert(3);
ms1.insert(4);
multiset::iterator it = ms1.begin();
while (it != ms1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//如果有多个相同key,find返回中序的第一个key
auto num = ms1.find(1);
while (num != ms1.end() && *num == 1)
{
cout << *num << " ";
num++;
}
cout << endl;
}
int main()
{
test_1();
test_2();
//test_3();
test_4();
return 0;
}
multiset是按照特定顺序存储元素的容器,其中多个元素可以具有等效值
相较于set,multiset允许有多个重复值出现,更符合单纯的排序,而非去重
其余属性特征与set类似
map是关联容器,用于存储由键值和映射值的组合形成的元素,遵循特定顺序
在map中,键值通常用于对元素进行排序和唯一标识,而映射值存储与此键关联的内容。键和映射值的类型可能不同
在内部,map中的元素始终按照其内部比较对象(类型为 Compare)指示的特定严格弱排序标准按其键排序
map中的映射值可以通过其相应的键使用括号运算符 (operator[ ]) 直接访问
map通常用二叉搜索树实现
函数名称 | 功能说明 |
empty() | 检验map是否为空 |
size() | 返回容器大小 |
max_size() | 返回容器最大容量 |
函数名称 | 功能说明 |
insert() | 默认尾插数据,如果数据已存在会返回现有元素迭代器 |
erase() | 删除数据 |
find() | 查找数据,返回数据迭代器 |
clear() | 清空map容器 |
count() | 对特定数值进行计数 |
其中insert如果插入的是相同的key,则会插入失败;value并不影响插入结果
函数名称 | 功能说明 |
operator[ ] | 如果 k 与容器中元素的键匹配,则该函数返回对其映射值的引用 如果 k 与容器中任何元素的键不匹配,则该函数将插入具有该键的新元素,并返回对其映射值的引用。请注意,这始终将容器大小增加 1,即使没有为元素分配映射值(元素是使用其默认构造函数构造的) |
at | 返回对用键 k 标识的元素的映射值的引用。 如果 k 与容器中任何元素的键不匹配,则该函数将引发out_of_range异常 |
mapped_type& operator[] (const key_type& k);
[ ]实际上具有四个功能:①插入②修改③插入+修改④查找。其中修是通过返回&value进行修改
#include