一、关联式容器概述
- STL内部预先定义好的关联式容器有:
- set:元素依据其value自动排序,每个元素只能出现一次,不允许重复
- multiset:和set的唯一差别是,其元素可以重复
- map:每个元素都是key/value pair,其中key是排序准则的基准。每个key只能出现一次,不允许重复。Map也被视为一种关联式数组,也就是“索引可为任意类型”的数组
- multimap:和map的唯一差别是,其元素都可以重复。multimap可被当做字典使用
- 关联式容器依据特定的排序准则,自动为其元素排序。元素可以是任何类型的value,也可以是key/value pair,其中key可以是任何类型,映射至一个相关value,而value也可以是任意类型
- 排序准则:
- 对于只有value的关联式容器,例如set、multiset,其对value进行排序。对于key/value pair的关联式容器,例如map、multimap,其根据key进行排序
- 默认情况所有容器都以操作符<进行排序,不过你可以提供自己的比较函数,定义出不同的排序准则
- 关联式的底层实现数据结构:
- 关联式容器拥有自动排序能力,并不意味着它们在排序方面的执行效能更高。实际上,由于股演练时容器每安插一个新元素都要进行一次排序,速度反而不及序列式容器经常采用的收发:先安插所有元素,然后调用STL提供的排序算法进行一次完全排序
二、set
格式
- set<value>:没有key与value之分,只有一个key数据,且默认为升序
- 头文件:#include <set>
特点:
- key不可以重复,默认为升序排序
- 不提供下标操作(下标运算符和at函数)
初始化:
升序、降序操作
- set的key默认为升序排序,我们也可以将key设置为显式地升序或者设置为降序排序
- 下面两个标准库函数(less、greater)都在头文件#include <xfunctional>中
- 先演示升序操作
//set<int> s; //升序
set<int, std::less<int>> s; //升序
s.insert(1);
s.insert(3);
s.insert(2);
for (const auto &w : s) {
cout << w<< endl;
}
set<int, std::greater<int>> s;
s.insert(1);
s.insert(3);
s.insert(2);
for (const auto &w : s) {
cout << w<< endl;
}
迭代器与遍历
- 当解引用一个关联容器迭代器时,我们得到的是容器的value_type的值的引用
- 重点:与map一样,set也只能够通过迭代器访问set的键值(key),但不能改变
set<int> iset = { 0,1,2,3,4 };
set<int>::iterator set_it = iset.begin();
while (set_it != iset.end()) {
*set_it = 666; //错误,不能改变值
cout << *set_it<< endl; //正确,可以读取值
}
添加元素(insert、emplace)
删除元素(erase)
演示案例:
- 我们将字符串输入保存到map中,将不想要统计的字符串事先定义在set中。然后统计字符串出现的次数
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
int main()
{
map<string, size_t> word_count;
set<string> exclude = { "The","a","but","and" };
string word;
while (cin >> word) {
find如果没有查找到,返回set的尾后迭代器
if(exclude.find(word)==exclude.end())
++word_count[word];
}
for (const auto &w : word_count) {
cout <<w.first <<":"<<w.second<<((w.second>1)?"times":"time")<< endl;
}
return 0;
}
value的不重复性
- set的key不可以重复,而multiset的key可以重复
- 下面用一个案例来演示这种情景
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
for (vector<int>::size_type i = 0; i < 10; i++) {
v.push_back(i);
v.push_back(i);
}
set<int> set1(v.begin(), v.end());
multiset<int> set2(v.begin(), v.end());
cout << v.size() << endl; //20
cout << set1.size() << endl;//10
cout << set2.size() << endl;//20
return 0;
}
其他操作
三、multiset
格式
- multiset<value>:没有key与value之分,只有一个key数据且默认为升序
- 头文件:#include <set>
特点
- key可以重复(如果有相同的key,则相邻存储)
- 不提供下标操作(下标运算符和at函数)
初始化
升序、降序操作
- multiset的key默认为升序排序,我们也可以将key设置为显式地升序或者设置为降序排序
- 下面两个标准库函数(less、greater)都在头文件#include <xfunctional>中
- 演示升序操作
multiset<int, std::less<int>> s; //升序
//multiset<int> s; //升序
s.insert(1);
s.insert(3);
s.insert(2);
for (const auto &w : s) {
cout << w<< endl;
}
multiset<int, std::greater<int>> s; //降序
s.insert(1);
s.insert(3);
s.insert(2);
for (const auto &w : s) {
cout << w<< endl;
}
迭代器与遍历
添加元素(insert、emplace)
删除元素(erase)
其他操作