c++ map和unordered_map怎么选择

选择策略

大多数情况下,应优先考虑使用unordered_map,除非使用场合要求key是有序的。

区别

mapunordered_map在使用接口上非常像,但是两者的实现方式不同,决定了两者的表现形式和性能是不一样的。
map使用红黑树实现,特点是有序,查找效率是O(log(n)),关于map更详细的使用和数据结构的组织可以看这里,下边是一个示意结构(仅显示key值)。

    8
   / \
  3   10
 / \    \
1   6    14
   / \   /
  4   7 13

unordered_map使用hash map组织元素,因此key是无序的,查找效率是O(1)。还是上边的key值,简单起见我们以H(key) = key MOD 8为hash函数,则下边是其组织结构的示意图:

|-8
|-1
|-10
|-3
|-4
|-13
|-6-14
|-7

关于效率

对于上边的这个例子,我们发现unordered_map的查找效率确实要比map快很多,比如我们查找key=7的元素,在map中我们要比较四次,分别是8 3 6 7,才可以得到想找的位置。可以对于unordered_map,我们直接取8的余,就得到了。
所以,这两个效率的比较是O(1)与树的高度的比较,当然这个效率不代表所有情况,例如对于14这个元素两者分别进行了三次和两次比较。
在更极端情况下,如果我们插入的元素的hash值都是一样的,那么,unordered_map的查找效率反而要坏于map了,例如下边的这种情况。

|-8-16-24-32-40-48-56
|
|
|
|
|
|
|

有序与无序

可以看出,对于map来说,无论元素添加的顺序是怎样的,在进入map之后都会进行排序,严格来说是有序的插入
unordered_map确是按照元素插入的顺序进行输出,即访问的。那么是否意味着只要有序的插入,就可以保证unordered_map有序的组织元素呢?答案是否定的,这种按照插入顺序的顺序进行的访问和输出,某种意义上只是一种巧合。严格说来,unordered_map的访问顺序是由采用的hash函数决定的。

#include <stdio.h>
#include <map>
#include <unordered_map>
#include <string>
#include <utility>   // used for pair
using std::map;
using std::unordered_map;
using std::string;
using std::pair;

int main()
{
   map<int, string> map_s;
   map_s.insert(pair<int, string>(2, "zhao"));
   map_s.insert(pair<int, string>(1, "qian"));
   map_s.insert(pair<int, string>(3, "sun"));
   printf("std:map:\n");
   for (auto& v : map_s)
   {
      printf("\t%d:%s\n", v.first, v.second.c_str());
   }

   unordered_map<int, string> map_us;
   map_us.insert(pair<int, string>(2, "zhao"));
   map_us.insert(pair<int, string>(1, "qian"));
   map_us.insert(pair<int, string>(3, "sun"));
   printf("unordered_map:\n");
   for (auto& v : map_us)
   {
      printf("\t%d:%s\n", v.first, v.second.c_str());
   }

   return 0;
}

以上代码的输出如下,

std:map:
	1:qian
	2:zhao
	3:sun
unordered_map:
	2:zhao
	1:qian
	3:sun

猜你喜欢

转载自blog.csdn.net/iceboy314159/article/details/105870443