当您需要排序时,请使用有序容器。事后对排序进行付出费用是毫无意义的。
您目前的解决方案是:
插入 O(1)
检索 O(N log N)
删除 O(N) (这是在不保留另一个索引的情况下得到的最好结果)
仅仅使用 std::multi_map,您可以实现:
插入 O(log N)
检索 O(log N) <-- 很大程度上比现有方案更好。我们需要找到范围的末尾。
删除 O(N)
现在,您可以通过 std::map< key, std::vector > 实现稍微更好的性能:
插入 O(log M),其中 M 是不同键的数目
检索 O(1) (begin 保证平摊常数时间)
删除 O(N)
您真正不能优化随机删除…除非您愿意保留另一个索引。例如:
typedef std::vector<value_type> data_value_t;
typedef std::map<key_type, data_value_t> data_t;
typedef std::pair<data_t::iterator,size_t> index_value_t;
// where iterator gives you the right vector and size_t is an index in it
typedef std::unordered_map<value_type, index_value_t> index_t;
但是,保持第二个索引的最新状态容易出错...并且会以其他操作为代价!例如,使用此结构,您将拥有:
- 插入 O(log M) --> 哈希映射中插入的复杂度为 O(1)
- 检索 O(N/M) --> 需要取消索引向量中的所有值,平均有 N/M 个
- 删除 O(N/M) --> 在哈希映射中查找 O(1),取消引用 O(1),从向量中删除 O(N/M),因为我们需要移动向量约一半的内容。使用 list 将产生 O(1)...但可能不会更快(取决于元素数量,因为存在内存权衡)。
另外,请记住,哈希映射复杂度是分摊的。触发重新分配,因为您超过了负载因子,这个特定的插入将花费很长时间。
我真的建议您使用 std::map>。这是性价比最高的选择。
vector
而不是list
,除非你确实拥有大量元素。 - Matthieu M.value
的唯一性,或者有其他东西来处理它? - Matthieu M.value
的唯一性。 - Giovanni Funchal