1.介绍

最近使用到一个c++的容器——unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。

1.1 特性

  1. 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)
  2. 无序性:使用hash表存储,内部无序
  3. Map : 每个值对应一个键值
  4. 键唯一性:不存在两个元素的键一样
  5. 动态内存管理:使用内存管理模型来动态管理所需要的内存空间

1.2 Hashtable和bucket

由于unordered_map内部采用的hashtable的数据结构存储,所以,每个特定的key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是十分形象的(像桶子一样,可以装多个元素)。可以参考这篇介绍哈希表的文章

所以unordered_map内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。

2. 模版

  1. template < class Key, // unordered_map::key_type
  2. class T, // unordered_map::mapped_type
  3. class Hash = hash<Key>, // unordered_map::hasher
  4. class Pred = equal_to<Key>, // unordered_map::key_equal
  5. class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type
  6. > class unordered_map;

主要使用的也是模板的前2个参数<键,值>(需要更多的介绍可以点击这里

  1. unordered_map<const Key, T> map;

2.1 迭代器

unordered_map的迭代器是一个指针,指向这个元素,通过迭代器来取得它的值。

  1. unordered_map<Key,T>::iterator it;
  2. (*it).first; // the key value (of type Key)
  3. (*it).second; // the mapped value (of type T)
  4. (*it); // the "element value" (of type pair<const Key,T>)

它的键值分别是迭代器的first和second属性。

  1. it->first; // same as (*it).first (the key value)
  2. it->second; // same as (*it).second (the mapped value)

3. 功能函数

3.1 构造函数

unordered_map的构造方式有几种:

- 构造空的容器

- 复制构造

- 范围构造

- 用数组构造

3.1.2示例代码

  1. // constructing unordered_maps
  2. #include <iostream>
  3. #include <string>
  4. #include <unordered_map>
  5. using namespace std;
  6. typedef unordered_map<string,string> stringmap;
  7. stringmap merge (stringmap a,stringmap b) {
  8. stringmap temp(a); temp.insert(b.begin(),b.end()); return temp;
  9. }
  10. int main ()
  11. {
  12. stringmap first; // 空
  13. stringmap second ( {{"apple","red"},{"lemon","yellow"}} ); // 用数组初始
  14. stringmap third ( {{"orange","orange"},{"strawberry","red"}} ); // 用数组初始
  15. stringmap fourth (second); // 复制初始化
  16. stringmap fifth (merge(third,fourth)); // 移动初始化
  17. stringmap sixth (fifth.begin(),fifth.end()); // 范围初始化
  18. cout << "sixth contains:";
  19. for (auto& x: sixth) cout << " " << x.first << ":" << x.second;
  20. cout << endl;
  21. return 0;
  22. }

输出结果:

  1. sixth contains: apple:red lemon:yellow orange:orange strawberry:red

3.2 容量操作

3.2.1 size

  1. size_type size() const noexcept;

返回unordered_map的大小

3.2.2 empty

  1. bool empty() const noexcept;

- 为空返回true

- 不为空返回false,和用size() == 0判断一样。

3.3 元素操作

3.3.1 find

  1. iterator find ( const key_type& k );

查找key所在的元素。

- 找到:返回元素的迭代器。通过迭代器的second属性获取值

- 没找到:返回unordered_map::end

3.3.2 insert

插入有几种方式:

- 复制插入(复制一个已有的pair的内容)

- 数组插入(直接插入一个二维数组)

- 范围插入(复制一个起始迭代器和终止迭代器中间的内容)

- 数组访问模式插入(和数组的[]操作很相似)

具体的例子可以看后面示例代码。

3.3.3 at

  1. mapped_type& at ( const key_type& k );

查找key所对应的值

- 如果存在:返回key对应的值,可以直接修改,和[]操作一样。

- 如果不存在:抛出 out_of_range 异常.

mymap.at(“Mars”) = 3396; //mymap[“Mars”] = 3396

3.3.4 erase

擦除元素也有几种方式:

  • 通过位置(迭代器)

    1. iterator erase ( const_iterator position );
  • 通过key

    1. size_type erase ( const key_type& k );
  • 通过范围(两个迭代器)

    1. iterator erase ( const_iterator first, const_iterator last );

3.3.5 clear

  1. void clear() noexcept

清空unordered_map

3.3.6 swap

  1. void swap ( unordered_map& ump );

交换两个unordered_map(注意,不是交换特定元素,是整个交换两个map中的所有元素)

3.3.7 示例代码

  1. // unordered_map::insert
  2. #include <iostream>
  3. #include <string>
  4. #include <unordered_map>
  5. using namespace std;
  6. void display(unordered_map<string,double> myrecipe,string str)
  7. {
  8. cout << str << endl;
  9. for (auto& x: myrecipe)
  10. cout << x.first << ": " << x.second << endl;
  11. cout << endl;
  12. }
  13. int main ()
  14. {
  15. unordered_map<string,double>
  16. myrecipe,
  17. mypantry = {{"milk",2.0},{"flour",1.5}};
  18. /****************插入*****************/
  19. pair<string,double> myshopping ("baking powder",0.3);
  20. myrecipe.insert (myshopping); // 复制插入
  21. myrecipe.insert (make_pair<string,double>("eggs",6.0)); // 移动插入
  22. myrecipe.insert (mypantry.begin(), mypantry.end()); // 范围插入
  23. myrecipe.insert ({{"sugar",0.8},{"salt",0.1}}); // 初始化数组插入(可以用二维一次插入多个元素,也可以用一维插入一个元素)
  24. myrecipe["coffee"] = 10.0; //数组形式插入
  25. display(myrecipe,"myrecipe contains:");
  26. /****************查找*****************/
  27. unordered_map<string,double>::const_iterator got = myrecipe.find ("coffee");
  28. if ( got == myrecipe.end() )
  29. cout << "not found";
  30. else
  31. cout << "found "<<got->first << " is " << got->second<<"\n\n";
  32. /****************修改*****************/
  33. myrecipe.at("coffee") = 9.0;
  34. myrecipe["milk"] = 3.0;
  35. display(myrecipe,"After modify myrecipe contains:");
  36. /****************擦除*****************/
  37. myrecipe.erase(myrecipe.begin()); //通过位置
  38. myrecipe.erase("milk"); //通过key
  39. display(myrecipe,"After erase myrecipe contains:");
  40. /****************交换*****************/
  41. myrecipe.swap(mypantry);
  42. display(myrecipe,"After swap with mypantry, myrecipe contains:");
  43. /****************清空*****************/
  44. myrecipe.clear();
  45. display(myrecipe,"After clear, myrecipe contains:");
  46. return 0;
  47. }

输出结果:

  1. myrecipe contains:
  2. salt: 0.1
  3. milk: 2
  4. flour: 1.5
  5. coffee: 10
  6. eggs: 6
  7. sugar: 0.8
  8. baking powder: 0.3
  9. found coffee is 10
  10. After modify myrecipe contains:
  11. salt: 0.1
  12. milk: 3
  13. flour: 1.5
  14. coffee: 9
  15. eggs: 6
  16. sugar: 0.8
  17. baking powder: 0.3
  18. After erase myrecipe contains:
  19. flour: 1.5
  20. coffee: 9
  21. eggs: 6
  22. sugar: 0.8
  23. baking powder: 0.3
  24. After swap with mypantry, myrecipe contains:
  25. flour: 1.5
  26. milk: 2
  27. After clear, myrecipe contains:

3.4 迭代器和bucket操作

3.4.1 begin

  1. iterator begin() noexcept;
  2. local_iterator begin ( size_type n );
  • begin() : 返回开始的迭代器(和你的输入顺序没关系,因为它的无序的)
  • begin(int n) : 返回n号bucket的第一个迭代器

3.4.2 end

  1. iterator end() noexcept;
  2. local_iterator end( size_type n );
  • end(): 返回结束位置的迭代器
  • end(int n) : 返回n号bucket的最后一个迭代器

3.4.3 bucket

  1. size_type bucket ( const key_type& k ) const;

返回通过哈希计算key所在的bucket(注意:这里仅仅做哈希计算确定bucket,并不保证key一定存在bucket中!)

3.4.4 bucket_count

  1. size_type bucket_count() const noexcept;

返回bucket的总数

3.4.5 bucket_size

  1. size_type bucket_size ( size_type n ) const;

返回第i个bucket的大小(这个位置的桶子里有几个元素,注意:函数不会判断n是否在count范围内)

3.4.6 示例代码

  1. // unordered_map::bucket_count
  2. #include <iostream>
  3. #include <string>
  4. #include <unordered_map>
  5. using namespace std;
  6. int main ()
  7. {
  8. unordered_map<string,string> mymap =
  9. {
  10. {"house","maison"},
  11. {"apple","pomme"},
  12. {"tree","arbre"},
  13. {"book","livre"},
  14. {"door","porte"},
  15. {"grapefruit","pamplemousse"}
  16. };
  17. /************begin和end迭代器***************/
  18. cout << "mymap contains:";
  19. for ( auto it = mymap.begin(); it != mymap.end(); ++it )
  20. cout << " " << it->first << ":" << it->second;
  21. cout << endl;
  22. /************bucket操作***************/
  23. unsigned n = mymap.bucket_count();
  24. cout << "mymap has " << n << " buckets.\n";
  25. for (unsigned i=0; i<n; ++i)
  26. {
  27. cout << "bucket #" << i << "'s size:"<<mymap.bucket_size(i)<<" contains: ";
  28. for (auto it = mymap.begin(i); it!=mymap.end(i); ++it)
  29. cout << "[" << it->first << ":" << it->second << "] ";
  30. cout << "\n";
  31. }
  32. cout <<"\nkey:'apple' is in bucket #" << mymap.bucket("apple") <<endl;
  33. cout <<"\nkey:'computer' is in bucket #" << mymap.bucket("computer") <<endl;
  34. return 0;
  35. }

输出结果:

  1. mymap contains: door:porte grapefruit:pamplemousse tree:arbre apple:pomme book:livre house:maison
  2. mymap has 7 buckets.
  3. bucket #0's size:2 contains: [book:livre] [house:maison]
  4. bucket #1's size:0 contains:
  5. bucket #2's size:0 contains:
  6. bucket #3's size:2 contains: [grapefruit:pamplemousse] [tree:arbre]
  7. bucket #4's size:0 contains:
  8. bucket #5's size:1 contains: [apple:pomme]
  9. bucket #6's size:1 contains: [door:porte]
  10. key:'apple' is in bucket #5
  11. key:'computer' is in bucket #6

最后

unordered_map常用的功能函数介绍就这么多了,还有一些比较不常用的功能的介绍,可以参考这里

关联容器:unordered_map详细介绍(附可运行代码)的更多相关文章

  1. AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码

    AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码 添加Watch应用对象时新增内容介绍 Watch应用对象添加到创建的项目中后,会包含两个部分:Watch App 和 Wa ...

  2. 关联容器:unordered_map详细介绍

    版权声明:博主辛辛苦苦码的字哦~转载注明一下啦~ https://blog.csdn.net/hk2291976/article/details/51037095 介绍 1 特性 2 Hashtabl ...

  3. PHP判断手机号运营商(详细介绍附代码)

    道理很简单,知道手机号规则 进行正则判断就可以 移动:134.135.136.137.138.139.150.151.157(TD).158.159.187.188 联通:130.131.132.15 ...

  4. PHP数组详细介绍(带示例代码)

    PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字典,集合 ...

  5. 【docker】【mysql】docker安装mysql,阿里云docker镜像加速器,docker搜索查看远程仓库上的镜像,docker拉取镜像,查看本地所有镜像,查看容器的运行状况,查看容器的详细信息

    在docker上安装mysql有两种方式 1.通过Dockerfile构建 2.直接在docker hub上拉取镜像安装 =================本篇采用方法2=============== ...

  6. swoole运行模式加速laravel应用的详细介绍

    本篇文章给大家带来的内容是关于swoole运行模式加速laravel应用的详细介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一.Swoole Swoole号称重新定义了PHP, ...

  7. java基础:进制详细介绍,进制快速转换,二维数组详解,循环嵌套应用,杨辉三角实现正倒直角正倒等腰三角,附练习案列

    1.Debug模式 1.1 什么是Debug模式 是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序. 1.2 Debug介绍与操作流程 如何加断点 选择 ...

  8. Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

    概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeMap.内容包括:第1部分 TreeMap介绍第2部分 TreeMa ...

  9. web.xml 详细介绍(转)

    web.xml 详细介绍 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧 ...

随机推荐

  1. ZOJ3704 I am Nexus Master! 2017-04-06 23:36 56人阅读 评论(0) 收藏

    I am Nexus Master! Time Limit: 2 Seconds      Memory Limit: 65536 KB NexusHD.org is a popular PT (Pr ...

  2. kali下firefox的安装

    在kali的系统中自带了一个firefox分支下的浏览器Iceweasel(Iceweasel是Mozilla Firefox浏览器的Debian再发布版),但是怎么说也配不上kali的强悍气势.还是 ...

  3. Zend_Application 流程详解

    本周没什么工作,zend 系统性的东西渐渐忘记,抽时间整理一下代码!Zend_Application 负责加载配置以及初始化资源,所以index.php 会有这行代码 /** Zend_Applica ...

  4. Android-进程理解/进程的优先级别

    进程理解 Android系统最小的控制单元是:进程 process 应用/CPU最小的控制单元是:线程 thread 一个应用一个 process 进程 一个应用一个 package(包是唯一的) 一 ...

  5. github注册与使用

    个人信息: 姓名:赵建 学号:1413042015 班级:网络工程141班 兴趣爱好:码代码,看电影,折腾linux github注册: 首先在地址栏输入https://www.github.com, ...

  6. 开源WebGIS实施方案(五):基于SLD实现图层符号化及其应用

    SLD概述 SLD(OpenGIS® Styled Layer Descriptor):图层样式注记.其当前版本是1.1.0.SLD是一种描述地图图层样式的标准,一般用于WMS中的图层符号化. 说白了 ...

  7. Mac和 iOS 下的对称和非对称加密算法的使用

    分享在Mac 和 iOS 上使用到的对称和非对称加密算法. 包括RSA,DSA, AES, DES, 3DES 和 blowfish 等等.因为要实现ssh协议, 所以用到了这些算法, 这些算法在ma ...

  8. asp.net 导出 Excel 身份证格式显示格式问题

    <%#  Eval("数据").ToString()+" " %> 加上    Excel 中 不会显示科学计数法

  9. 其他信息: 实体类型 xxxxx 不是当前上下文的模型的一部分。

    我是手动添加的EF类的,   解决方法: 没有在DbContext 添加  public virtual DbSet<xxx> xxxx{ get; set; } 导致不在上下文中

  10. 巧用网页开发者工具F12 审查、修改元素、去除广告、屏蔽遮罩

    巧用网页开发者工具F12 审查.修改元素.去除广告.屏蔽遮罩 每当打开一个网页的时候,是否为页面有很多广告而烦恼:是否为要操作页面(例如观看超清视频),请先注册登录等等事情而麻烦:是否对网页加锁的视频 ...