我正在尝试比较某些操作的stl map和stl unordered_map。我在网上看了一下,这只会增加我对哪一个整体更好的疑虑。所以我想根据他们执行的操作来比较两者。
哪一个在
中表现得更快插入,删除,查找
哪一个占用更少的内存,更少的时间从内存中清除它。任何解释都热烈欢迎!!!
提前致谢
答案 0 :(得分:10)
哪一个在插入,删除,查找中表现得更快?哪一个占用更少的内存,更少的时间从内存中清除它。任何解释都热烈欢迎!!!
对于特定用途,你应该尝试使用你的实际数据和使用模式,看看哪个实际上更快......有足够的因素,假设任何一个总是“赢”是危险的。
学术上 - 随着元素数量向无穷大增加,std::unordered_map
上的那些操作(这是为计算科学提供的“哈希映射”或“哈希表”提供的C ++库)将继续花费相同的时间O(1)(忽略内存限制/缓存等),而使用std::map
(平衡二叉树)每次元素数量加倍时,通常需要额外做一个比较操作,因此逐渐变慢O(log 2 n)。
std::unordered_map
实现necessarily use open hashing:基本的期望是会有一个连续的“桶”数组,每个逻辑上都是任何值的容器。
它通常用于将哈希表描绘为vector<list<pair<key,value>>>
,其中从向量元素到值的值从至少一个指针解除引用,当您按照列表头指针存储时在桶中到初始列表节点;插入/查找/删除操作的性能取决于列表的大小,平均等于unordered_map
的{{3}}。
如果load_factor
降低(默认值为1.0),则插入过程中会有更少的冲突但更多的重新分配/重新散列以及更多的内存浪费(这可能会通过增加缓存未命中而影响性能)。
这个最明显的unordered_map
实现的内存使用涉及max_load_factor
list-head-iterator /指针大小的桶的连续数组和每个键/值的一个双向链接列表节点对。通常,bucket_count()
+ 2 * size()
额外的开销指针,根据实现可能执行的动态内存分配请求大小的任何舍入进行调整。例如,如果要求100个字节,则可能会得到128或256或512.实现的动态内存例程也可能使用一些内存来跟踪已分配/可用的区域。
尽管如此,C ++标准为实际实现留出了空间,可以做出一些自己的性能/内存使用决策。例如,在分配一个新的更大的阵列之后,它们可以将旧的连续桶阵列保持一段时间,因此可以逐步地将值重新组合到后者中,以便以平均情况性能为代价来降低最坏情况的性能。在操作期间咨询两个阵列。
map
是一个二叉树,可以使用指针链接不同调用返回到new
的不同堆内存区域。除了键/值数据,树中的每个节点都需要父指针,左指针和右指针(如果丢失,请参阅bucket_count()
)。
因此,unordered_map
和map
都需要为键/值对分配节点,前者通常具有上/下一节点链接的双指针/迭代器开销,后者有三个为父/左/右。但是,unordered_map
还为bucket_count()
存储分配了一个连续的分配(== size()
/ load_factor()
)。
对于大多数目的而言,内存使用量并没有显着差异,并且一个额外区域的释放时间差异不太可能引人注意。
对于容器填充前面然后重复搜索而没有进一步插入/删除的情况,有时使用标准算法wikipedia's binary tree article,binary_search
,{{ 3}},equal_range
。这具有单个连续内存分配的优点,其更加缓存友好。它总是优于map
,但unordered_map
可能仍然更快 - 如果你关心的话可以衡量。
答案 1 :(得分:2)
两者兼顾的原因是两者都不是更好。
使用任何一个。切换,如果另一个证明更好的使用。
答案 2 :(得分:1)
您的问题的答案在很大程度上取决于您正在使用的特定STL实现。实际上,您应该查看STL实现的文档 - 它可能会有大量关于性能的信息。
一般而言,根据cppreference.com,maps通常实现为red-black trees并支持时间复杂度为O(log n)的操作,而unordered_maps通常支持常量 - 时间操作。 cppreference.com对内存使用情况缺乏洞察力;但是,another StackOverflow answer建议地图通常使用的内存少于unordered_maps。
对于使用Visual Studio 2012的STL实现Microsoft软件包,看起来map在分摊的O(log n)时间内支持这些操作,unordered_map在分摊的常量时间内支持它们。但是,文档没有明确说明内存占用情况。
答案 3 :(得分:1)
<强>地图强>
插入:
删除:
查找
无序地图:
插入:
删除:
查找
了解这些,您可以根据实现的类型决定使用哪个容器。
来源:www.cplusplus.com