STL中提供的关联式容器,set和map(multiset和multimap),包括在C++ 11中新增的无序关联容器unordered_map、unordered_multimap、unordered_set 以及 unordered_multiset。
一、关联式容器
1.关联式容器在存储元素值的同时,还会为各元素额外再配备一个值(又称为“键”,其本质也是一个 C++ 基础数据类型或自定义类型的元素),它的功能是在使用关联式容器的过程中,如果已知目标元素的键的值,则直接通过该键就可以找到目标元素,而无需再通过遍历整个容器的方式。
2.选用关联式容器存储元素,往往就是看中了关联式容器可以快速查找、读取或者删除所存储的元素,同时该类型容器插入元素的效率也比序列式容器高。
3.使用关联式容器存储的元素,都是一个一个的“键值对”( <key,value> ),这是和序列式容器最大的不同。除此之外,序列式容器中存储的元素默认都是未经过排序的,而使用关联式容器存储的元素,默认会根据各元素的键值的大小做升序排序。关联式容器存储底层选用了 「红黑树」。对应哈希容器,底层为哈希表,且不会自动排序。
二、pair
“键值对”并不是普通类型数据,C++ STL 标准库提供了 pair 类模板,其专门用来将 2 个普通元素 first 和 second(可以是 C++ 基本数据类型、结构体、类自定的类型)创建成一个新元素<first, second>。
1.构造与赋值
pair();
pair (const first_type& a, const second_type& b);
template<class U, class V> pair (const pair<U,V>& pr);
// 调用构造函数 1,也就是默认构造函数
pair <int, int> pair1;
// 调用第 2 种构造函数
pair <int, int> pair2(1,1);
// 调用拷贝构造函数
pair <int, int> pair3(pair2);
//make_pair 形式进行赋值
pair <int, int> pair4 = make_pair(1, 1);
//直接对first second 进行赋值
pair1.first = 1;
pair1.second = 1;
2.判断与交换
1)对于进行比较的 2 个 pair 对象,其对应的键和值的类型必须相同,否则将没有可比性,同时编译器提示没有相匹配的运算符,即找不到合适的重载运算符。
2)pair类模板还提供有一个 swap() 成员函数,能够互换 2 个 pair 对象的键值对,其操作成功的前提是这 2 个 pair 对象的键和值的类型要相同。
三、set
1.set/multiset
set实际上是由pair组成的,只不过要求key的值和元素值相同,插入元素时自动从小到大排序,底层由二叉树结构实现,set中不允许有重复元素,而multiset可以。本质上是因为,set的insert函数插入数据的同时会返回插入结果,表示插入是否成功,而multiset不会检测数据,因此可以插入重复数据。
1)构造
set<T> st;
//默认构造函数set(const set &st);
//拷贝构造函数
2)赋值
set& operator=(const set &st);
//重载等号操作符
3)大小
size();
//返回容器中元素的数目empty();
//判断容器是否为空
4)插入删除
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(elem);
//删除容器中值为elem的元素。
5)查找
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();count(key);
//统计key的元素个数
2.unordered_set
unordered_set 容器具有以下几个特性:
不再以键值对的形式存储数据,而是直接存储数据的值;容器内部存储的各个元素的值都互不相等,且不能被修改;不会对内部存储的数据进行排序。
四、map
1.map/multimap
map中所有元素都是pair,pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值),自动由小到大排序。map不允许容器中有重复key值元素,multimap允许容器中有重复key值元素。
1)构造
map<T1, T2> mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数
pair<string, int> p("10", 20);
map<string, int> m1;
m1.insert(p);
m1.insert(make_pair("100", 200));
m1.insert(pair<string, int>("1000", 2000));
2)赋值
map& operator=(const map &mp);
//重载等号操作符
3)大小
size();
//返回容器中元素的数目empty();
//判断容器是否为空
4)插入删除
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);
//删除容器中值为key的元素。
5)查找
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();count(key);
//统计key的元素个数
2.unordered_map
unordered_map 容器和 map 容器仅有一点不同,即 map 容器中存储的数据是有序的,而 unordered_map 容器中是无序的。