本节我们开始学习unordered_map容器。从功能上看,对比map容器,unordered_map容器既能够通过'[]'访问元素,又能够通过at()成员函数访问元素,同时还保证键值存在的唯一性,与map容器极为“相似”,唯一不同点就是unordered_map容器没有按键(key)进行自动排序;从结构上看,对比map容器,两者又是完全不一样的独立存在,map容器底层基于红黑树,元素平均访问时间复杂度为O(log n),而unordered_map容器底层基于哈希表,能够通过键(key)来快速获取值(value),这使得unordered_map容器的元素访问效率远远高于map容器。unordered_map容器就是这么一个“独特”的存在,让我们通过代码来认识它吧。
如何创建unordered_map容器?其创建方式与map容器别无二致,具体创建方式如下:
#include <iostream> #include<unordered_map>//需要包含头文件 #include<string> using namespace std; /*unordered_map创建并初始化*/ void test() { unordered_map<string,string> ump1;//直接创建 unordered_map<string,string> ump2{ {"C语言网","dotcpp.com"}, {"C语言教程","https://www.dotcpp.com/BbNkeAOzdW.php/cms/archives?ref=addtabs"}, {"计算机二级C语言","https://www.dotcpp.com/course/erjic/"}, {"数据结构教程","https://www.dotcpp.com/course/ds/"} };//初始化列表 unordered_map<string,string> ump3(ump2);//拷贝构造 unordered_map<string,string> ump4; ump4=ump2;//'='运算符重载 unordered_map<string,string> ump5(ump2.begin(),ump2.end());//通过同类型迭代器范围创建 } int main() { test(); return 0; }
代码成功编译,unordered_map容器创建成功!
unordered_map容器也有很多同map容器类似的接口,比如insert()、 erase()、find()和count()等。重点在于区分它们之间不同的接口!记住lower_bound(key)和upper_bound(key)仅仅存在于map容器里,而rehash(n)、reserve(n)等与哈希相关的成员函数仅仅存在于unordered_map容器里,切勿混淆使用。下面我们将通过表格认识unordered_map容器常用的成员函数。
成员函数 | 参数 | 功能描述 |
---|---|---|
clear | 无 | 清空容器中的所有元素 |
empty | 无 | 检查容器是否为空 |
size | 无 | 返回容器中元素的数量 |
begin | 无 | 返回指向容器第一个元素的迭代器 |
end | 无 | 返回指向容器尾后位置的迭代器 |
cbegin | 无 | 返回指向容器第一个元素的const迭代器 |
cend | 无 | 返回指向容器尾后位置的const迭代器 |
bucket_count | 无 | 返回哈希表中桶的数量 |
max_bucket_count | 无 | 返回容器能容纳的最大桶数量 |
load_factor | 无 | 返回当前负载因子(元素数量/桶数量) |
max_load_factor | 无 | 返回最大负载因子 |
hash_function | 无 | 返回哈希函数对象 |
key_eq | 无 | 返回键相等性比较函数对象 |
get_allocator | 无 | 返回分配器对象 |
max_size | 无 | 返回容器可容纳的最大元素数量 |
operator[] | const Key& key | 访问或插入元素。如果key不存在,会插入默认值并返回引用 |
key_type&& key | 访问或插入元素(移动语义)。如果key不存在,会插入默认值并返回引用 | |
at | const Key& key | 访问指定键的元素。如果key不存在,抛出out_of_range异常 |
insert | const value_type& value | 插入键值对。如果键已存在,插入失败 |
value_type&& value | 插入键值对(移动语义)。如果键已存在,插入失败 | |
InputIterator first, InputIterator last | 插入迭代器范围内的所有元素 | |
initializer_list<value_type> il | 插入初始化列表中的所有元素 | |
const_iterator hint, const value_type& value | 在提示位置插入元素,可能提高插入效率 | |
const_iterator hint, value_type&& value | 在提示位置插入元素(移动语义),可能提高插入效率 | |
emplace | Args&&... args | 原地构造元素,避免不必要的拷贝或移动操作 |
emplace_hint | const_iterator hint, Args&&... args | 在提示位置原地构造元素,可能提高插入效率 |
erase | const_iterator position | 删除指定位置的元素 |
const key_type& key | 删除指定键的元素,返回删除的元素数量 | |
const_iterator first, const_iterator last | 删除迭代器范围内的元素 | |
find | const key_type& key | 查找指定键的元素,返回迭代器,未找到返回end() |
count | const key_type& key | 返回指定键的出现次数(0或1) |
contains | const key_type& key | 检查容器是否包含指定键(C++20) |
equal_range | const key_type& key | 返回包含所有键为key的元素的范围(pair迭代器) |
bucket | const key_type& key | 返回键key所在的桶编号 |
bucket_size | size_type n | 返回第n个桶中的元素数量 |
max_load_factor | float z | 设置最大负载因子 |
rehash | size_type n | 设置桶数量为至少n,重新哈希所有元素 |
reserve | size_type n | 预留空间以容纳至少n个元素而不触发重哈希 |
swap | unordered_map& ump | 交换两个容器的内容 |
虽然unordered_map容器成员函数很多,但是我们只要把它类比map容器使用,然后记住自身“特殊”的成员函数,我们就能够轻松驾驭unordered_map容器。下面让我们通过代码来简单了解其常用成员函数的使用方法。
#include <iostream> #include<unordered_map>//需要包含头文件 #include<string> using namespace std; /*unordered_map容器常用函数的使用方法*/ void test() { unordered_map<string,string> ump{ {"C语言网","dotcpp.com"}, {"C语言教程","https://www.dotcpp.com/BbNkeAOzdW.php/cms/archives?ref=addtabs"}, {"计算机二级C语言","https://www.dotcpp.com/course/erjic/"}, {"数据结构教程","https://www.dotcpp.com/course/ds/"} };//初始化列表 ump.emplace("Linux命令","https://www.dotcpp.com/course/linuxcmd/") ;//插入元素 cout << "我们通过C语言网学习编程,其网址为:【" <<ump["C语言网"] << "】\n"; ump.erase("C语言网");//删除键(key) cout << "C语言网还有其他教程,分别是:\n" ; /*迭代器遍历ump*/ for(unordered_map<string,string>::iterator it = ump.begin();it!=ump.end();++it) { cout <<"想要学习" << it->first << ",其的网址是:【" << it->second << "】\n"; } } int main() { test(); return 0; }
编译结果如下:
这里推荐读者保存网址,当需要查看unordered_map 容器常用成员函数时方便随时跳转。
总结:本节我们主要通过对比map容器学习了unordered_map 容器的创建及初始化,同时我们还通过表格和代码实际操作其部分成员函数,掌握了unordered_map 容器常用的一些基本用法。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程