Map容器
Posted 野渡书生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Map容器相关的知识,希望对你有一定的参考价值。
1、Map
(1)定义
Map是标准关联式容器(associative container)之一,一个map是一个键值对序列,即(key ,value)对。它提供基于key的快速检索能力,在一个map中key值是唯一的。map提供双向迭代器,即有从前往后的(iterator),也有从后往前的(reverse_iterator)。
Map要求能对key进行<操作,且保持按key值递增有序,因此map上的迭代器也是递增有序的。如果对于元素并不需要保持有序,可以使用hash_map。
Map中key值是唯一的,如果已存在一个键值对(name,code):("name_a",1),而我们还想插入一个键值对("name_a",1)则会报错(不是报错,准确的说是,返回插入不成功!)。而我们又的确想这样做,即一个键对应多个值,multimap可实现这个功能。
(2)底层实现
Map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,默认用的是小于号,即less<>。
Map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
Map在空间上的特性,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),这些地方很费内存。
(3)特点
Map类似于数据库中的1:1关系,它是一种关联容器,提供一对一(C++ primer中文版中将第一个译为键,每个键只能在map中出现一次,第二个被译为该键对应的值)的数据处理能力,这种特性了使得map类似于数据结构里的红黑二叉树。Multimap类似于数据库中的1:N关系,它是一种关联容器,提供一对多的数据处理能力。
(4)性能分析
a)、hash_map和map的区别在哪里?
(1)构造函数 hash_map需要hash函数,等于函数;map只需要比较函数(小于函数)。
(2)存储结构 hash_map采用hash表存储,map一般采用红黑树实现。因此内存数据结构是不一样的。
b)、什么时候需要使用hash_map,什么时候需要map?
总体来说,hash_map 查找速度会比map快,而且查找速度基本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。
但若你对内存使用特别严格,希望程序尽可能少消耗内存,那么一定要小心,hash_map可能会让你陷入尴尬,特别是当你的hash_map对象特别多时,你就更无法控制了,而且 hash_map的构造速度较慢。
因此,选择的时候需要权衡三个因素: 查找速度,数据量,内存使用。
c)、如何用hash_map替换程序中已有的map容器?
这个很容易,但需要你有良好的编程风格。建议你尽量使用typedef来定义你的类型:
当你希望使用hash_map来替换的时候,只需要修改:
其他的基本不变。当然,你需要注意是否有Key类型的hash函数和比较函数。
2、成员函数
(1)构造函数
经过分析发现,map的构造函数主要是调用“拷贝构造函数”和利用“迭代器”进行初始化两种方式,因为map中每个节点由一对值构成。
(2)插入操作
示例:
以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的:第一种和第二种在效果上是一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,如下:
上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么我们怎么知道insert语句是否插入成功,可以用pair来获得是否插入成功,程序如下:
我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话:Insert_Pair.second应该是true的,否则为false。
下面给出完成代码,演示插入成功与否问题:
用如下程序,看下用数组插入在数据覆盖上的效果:
(3)删除操作
示例:
(4)定位查找
示例:
(5)数据大小
max_size(); //返回map容器可能包含的元素最大个数 size(); //返回当前map容器中的元素个数 count(); //用来查找map中某个某个键值出现的次数;
示例:
(6)遍历操作
示例:
(7)排序操作
示例:
以上是关于Map容器的主要内容,如果未能解决你的问题,请参考以下文章