所以我一直在研究不同的unordered_map函数调用的排序效率。以下是同一代码中的两种可能的工作方式。
注意:keywordMap是一个无序映射,它将字符串映射到自制结构的向量(这是e的类型)。这是在循环中完成的。
第一个选项:
auto curKeyWord = someString;
auto curEntryPair = keywordMap.insert(
make_pair( move(curKeyWord), vector<entry*>{e} ) );
if (!curEntryPair.second){//insertion failed
curEntryPair.first->second.push_back(e);
}
第二个选项:
auto curKeyWord = someString;
auto curEntry = keywordMap.find(curKeyWord);
if( curEntry == end(keywordMap) ){//DNE in map
keywordMap.emplace( make_pair( move(curKeyWord), vector<entry*>{e} ) );
}
else{
curEntry->second.push_back(e);
}
我对哪些代码块更快感兴趣。问题实际上归结为.insert的工作原理。如果insert基本上用作查找键应该在哪里并且如果它不存在则插入它,那么第一个应该更快,因为它只是一个探测器。一旦我调用了insert,如果插入没有做任何事情,我就需要调用push_back。然而,这也是非常丑陋的。我也很好奇,如果插入具有相同的问题,那么它在检查地图中是否存在密钥之前构造元素。
我可能需要对这两段代码进行基准测试,但我想知道是否有任何我想念的信息会告诉我现在的答案。
答案 0 :(得分:0)
一般来说,第一位代码更快,因为它执行单一查找。
以下是在map中执行插入/覆盖的常用方法:
auto rv = map.insert(std::make_pair(key, value));
if (!rv.second)
rv.first->second = value;
这里的要点是std::map
通常实现为平衡二叉树(谷歌:红/黑树),因此insert()
和find()
都取O(log(n) ) 脚步。 IE容器具有自然的内部订单,插入必须将新项目放在正确的位置。 (这就是密钥必须严格按顺序排列的原因。)
std::unordered_map
使用散列,因此对于默认构造的映射,查找为O(1)(即每个桶中只有一个项目)。一旦允许冲突(即每个桶中有k
个项目),每次查找都需要O(k)步。
现在,回到最初的问题 - 做更少的工作总是更好。 std :: unordered_map情况的差异非常小(第二次查找在默认情况下以O(1)步骤发生)。