哪一个在以下方面的表现更快:
插入、删除、查找
哪一个占用更少的内存,并且清除内存所需的时间更短。欢迎任何解释!
谢谢!
std::unordered_map
的实现必须使用开放式哈希:基本期望是将有一个连续的"桶"数组,每个逻辑上都是任何值的容器。
通常将哈希表视为一个vector<list<pair<key,value>>>
,其中从向量元素到值的获取涉及至少一个指针解引用,因为您跟随存储在桶中的列表头指针到初始列表节点;插入/查找/删除操作的性能取决于列表的大小,这平均等于unordered_map
的load_factor
。
如果降低max_load_factor
(默认值为1.0),则会发生更少的冲突,但在插入期间会发生更多的重新分配/重新哈希和浪费内存(可能通过增加高速缓存未命中来损害性能)。
unordered_map
实现的内存使用情况包括bucket_count()
个列表头迭代器/指针大小的连续数组和每个键值对的一个双向链表节点。通常,会有bucket_count()
+2*size()
额外指针开销,根据实现可能会对动态内存分配请求大小进行舍入调整。例如,如果您请求100字节,则可能获得128、256或512字节。实现的动态内存例程可能还会使用一些内存来跟踪已分配/可用区域。map
是一种二叉树,通常使用指针链接由不同的new
调用返回的不同堆内存区域。除了键/值数据外,树中的每个节点还需要父、左和右指针(如果迷失,请参见维基百科的二叉树文章)。
因此,无序unordered_map
和map
都需要为键/值对分配节点,前者通常具有两个指针/迭代器开销以进行prev/next-node链接,后者则具有三个指针以进行parent/left/right链接。但是,unordered_map
还具有单个连续分配的bucket_count()
桶(== size()
/ load_factor()
)。
对于大多数目的来说,这在内存使用方面并没有明显的差异,而为一个额外区域释放内存的时间差异不太可能引起注意。
对于那些事先填充容器,然后反复搜索而没有进一步插入/删除的情况,使用排序向量可能是最快的选择,使用标准算法binary_search
, equal_range
, lower_bound
, upper_bound
进行搜索。这样做的优点是单个连续的内存分配,更加缓存友好。它总是比map
更快,但unordered_map
可能仍然更快 - 如果您关心性能,请进行测量。
之所以有这两种选择,是因为它们各有优劣。
可以使用任意一种。如果另一种对您的使用更好,请切换到另一种。
map
更好内存使用的 unordered_map
是可以想象的吗? - Andrew Durward你的问题的答案很大程度上取决于你使用的特定STL实现。实际上,你应该查看你的STL实现文档 - 它可能会有很多关于性能的信息。
总的来说,根据cppreference.com的说法,maps通常被实现为red-black trees并支持时间复杂度为O(log n)的操作,而unordered_maps通常支持常数时间操作。cppreference.com对内存使用提供了很少的见解; 然而,另一个StackOverflow答案表明,相比unordered_maps,maps通常使用更少的内存。
对于 Visual Studio 2012 打包的 STL 实现,看起来 map 支持这些操作的摊销 O(log n) 时间,而 unordered_map 支持摊销常数时间。然而,文档没有明确说明内存占用。
映射:
插入:
删除:
查找:
无序映射:
插入:
单个元素插入: 1. 平均情况:常数时间。 2. 最坏情况:与容器大小成线性关系。