一、基本原理
unordered_map是C++标准库提供的关联容器之一,保存的是键值对(key-value),我们可以通过key快速查找到其对应的value。unordered_map底层使用的数据结构是哈希表(hash table),因此在unordered_map中查找、添加或删除元素时间复杂度都是常数时间O(1)。此外,unordered_map中的元素是无序的。
unordered_map使用场景:
现在假设有一个寝室501,寝室有4个学生,我们要用一种容器来保存这4个学生的学号和姓名,需求是我要通过学号来查找这个学号对应的姓名。
此时我们用一个unordered_map来保存,学号作为key,姓名作为value,一个学生的这两个信息作为unordered_map的一个元素pair(pair用法总结),我们可以通过学号来得到对应的姓名。
也许你会有这样的疑问,为什么要用unordered_map呢,我用一个二维数组不是也一样能存放寝室4个学生的学号和姓名吗?
是的,存是可以存,但是操作的时间复杂度就不一样了,比如我知道学号"sc0303",我想查找对应的姓名,如果用unordered_map保存的,根据哈希表的特性,只需要O(1)的时间就能查到对应的姓名。如果用的二维数组保存的,需要从头遍历二维数组的第一列,需要O(n)的时间才能查到。这就是使用unordered_map的意义。
也许你还会有这样的疑问,为什么要用unordered_map呢,我用一个map也一样能存吗?
用map和unordered_map的区别在于,map基于红黑树,是按关键字有序排列的,unordered_map基于哈希表,是散列存放的(无序)。当你需要进行范围查询“比学号sc0302大的同学的姓名”,那么使用map就更方便,因为map中元素已经按照学号(关键字)有序排好了,但是如果这种场景下使用unordered_map,你要进行范围查找只能一个一个去比较了。在进行等值查询时unordered_map只需要O(1)的时间就能查到,但map却需要O(log(n))的时间,因此等值查询时使用unordered_map更快。
具体选用哪种容器还是要看使用场景,它们各有优势。
二、用法
unordered_map中的元素是一对对键值对,类型pair,用法可参考博客pair用法总结
初始化
unordered_map<T1,T2> 容器名; | T1、T2是类型名,可以是基本数据类型int、double等,也可以是类类型string等 |
---|---|
unordered_map<T1,T2> m1; | 创建一个名为m1的空unordered_map,key的类型为T1,value的类型为T2 |
unordered_map<T1,T2> m1{p1,p2……}; | m1中的元素被初始化为p1,p2……,p1、p2是pair类型 |
unordered_map<T1,T2> m1{ {key1,value1},{key2,value2}……}; | m1中的元素被初始化为 键值对{key1,value1},{key2,value2}…… |
unordered_map<T1,T2> m2(m1); | m2中包含和m1一样的元素 |
unordered_map<T1,T2> m2=m1; | m2中包含和m1一样的元素 |
程序示例:
pair<string, string> p1("sc0301","小杨"); // 方式一,创建一个pair名为p1
pair<string, string> p2 = make_pair("sc0302", "小马"); // 方式二,make_pair函数返回一个用"sc0302"和 "小马"初始化的pair
pair<string, string> p3("sc0303", "小王");
pair<string, string> p4("sc0304", "小何");
unordered_map<string, string> m1; // 创建一个空unordered_map
unordered_map<string, string> m2{
p1,p2,p3,p4 }; // 创建一个包含键值对p1、p2、p3、p4的unordered_map
unordered_map<string, string> m3{
{
"sc0301","小杨"},{
"sc0302", "小马"},{
"sc0303", "小王"},{
"sc0304", "小何"} }; // 效果同上一句
unordered_map<string, string> m4(m2); // 创建一个unordered_map,m4中包含和m2一样的元素
unordered_map<string, string> m5 = m2; // 创建一个unordered_map,m5中包含和m2一样的元素
访问元素
访问元素 | |
---|---|
T2 value = m1[key]; | 得到关键字key对应的值value |
m1.at(key); | 得到关键字key对应的值value |
*iter | 访问迭代器iter指向的元素 |
获取迭代器 | |
---|---|
m1.begin(); | 获取指向m1首元素的迭代器 |
m1.end(); | 获取指向m1尾元素的后一个位置的迭代器 |
m1.rbegin(); | 获取指向m1首元素的前一个位置的迭代器 |
m1.rend(); | 获取指向m1尾元素的迭代器 |
m1.cbegin(); m1.cend(); | 含义同上,但获取到的是const_iterator |
m1.crbegin(); m1.crend(); | 含义同上,但获取到的是const_iterator |
程序示例:
string p2_name = m2["sc0302"]; // 得到学号(关键字)"sc0302"对应的姓名(值)
string p3_name = m2.