map和set的异同

异同分析

MAP的节点是一对数据.
SET的节点是一个数据.

map使用关键值Key来唯一标识每一个成员, map的value值可以重复。
set存储已排序的无重复的元素。

都属于关联容器 ,形式不同:

map的形式   map<type1, type2>   mymap;   
set的形式   set<type>   myset;  

set(集合)——包含了经过排序了的数据,这些数据的值(value)必须是唯一的,系统会根据该值来自动将数据排序。

map(映射)——经过排序了的二元组的集合,map中的每个元素都是由两个值组成,其中的key(键值,一个map中的键值必须是唯一的)是在排序或搜索时使用,它的值可以在容器中重新获取;而另一个值是该元素关联的数值。比如,除了可以ar[43] = “overripe”这样找到一个数据,map还可以通过ar[“banana”] = “overripe”这样的方法找到一个数据。如果你想获得其中的元素信息,通过输入元素的全名就可以轻松实现。

map是映射集合中的元素不能重复,set可以进行集合的各种操作(交并补等),当然你也可以用list或vector实现set,但是效率会很低。内部结构采用红黑树的平衡二叉树。multiset 跟set 类似,唯一的区别是允许键值重复!!!。
映射是一种一一对应的关系,哈希表也可以看作是映射的一种。映射通常可用来实现字典结构(dictionary)。

map和set的优点

C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,map和 set封装了二叉树等,在封装这些数据结构的时候,STL按照程序员的使用习惯,以成员函数方式提供的常用操作,如:插入、排序、删除、查找等。让用户在 STL使用过程中,并不会感到陌生。

C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般的平衡二叉树。

1、为何map和set的插入删除效率比用其他序列容器高?

因为对于关联容器来说,不需要做内存拷贝和内存移动。map和set容器内所有元素都是以节点的方式来存储,其节点结构和链表差不多,指向父节点和子节点。结构图可能如下:

        A
       / /
      B   C
     / / / /
    D E F G

因此插入的时候只需要稍做变换,把节点的指针指向新的节点就可以了。删除的时候类似,稍做变换后把指向删除节点的指针指向其他节点就OK了。这里的一切操作就是指针换来换去和内存移动没有关系!!!

2、为何每次insert之后,以前保存的iterator不会失效?

iterator在这里就相当于指向节点的指针,内存没有变,指向内存的指针怎么会失效呢(当然被删除的那个元素本身已经失效了)。相对于vector来说,每一次删除和插入,指针都有可能失效,调用push_back在尾部插入也是如此。因为为了保证内部数据的连续存放,iterator指向的那块内存在删除和插入过程中可能已经被其他内存覆盖或者内存已经被释放了。即使时push_back的时候,容器内部空间可能不够,需要一块新的更大的内存,只有把以前的内存释放,申请新的更大的内存,复制已有的数据元素到新的内存,最后把需要插入的元素放到最后,那么以前的内存指针自然就不可用了。特别是在和find等算法在一起使用的时候,牢记这个原则:不要使用过期的iterator

3、为何map和set不能像vector一样有个reserve函数来预分配数据?

究其原理来说时,引起它的原因在于在map和set内部存储的已经不是元素本身了,而是包含元素的节点。也就是说map内部使用的Alloc并不是map<Key, Data, Compare, Alloc>声明的时候从参数中传入的Alloc。例如:

map<int, int, less<int>, Alloc<int> > intmap;

这时候在intmap中使用的allocator并不是Alloc<int>, 而是通过了转换的Alloc,具体转换的方法是在内部通过Alloc<int>::rebind重新定义了新的节点分配器,详细的实现参看彻底学习STL中的Allocator。其实你就记住一点,在map和set里面的分配器已经发生了变化,reserve方法你就不要奢望了。

4、当数据元素增多时(10000和20000个比较),map和set的插入和搜索速度变化如何?

如果你知道log2的关系你应该就彻底了解这个答案。在map和set中查找是使用二分查找,也就是说,如果有16个元素,最多需要比较4次就能找到结果,有32个元素,最多比较5次。那么有10000个呢?最多比较的次数为log10000,最多为14次,如果是20000个元素呢?最多不过15次。看见了吧,当数据量增大一倍的时候,搜索次数只不过多了1次,多了1/14的搜索时间而已。你明白这个道理后,就可以安心往里面放入元素了。

    原文作者:爱橙子的OK绷
    原文地址: https://blog.csdn.net/will130/article/details/50865790
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞