繁体   English   中英

如何使用带有“外部”键的 std::unordered_map

[英]How to use std::unordered_map with 'external' keys

我的目标是编写一个 class,它的工作原理类似于 unordered_map,但保持元素的插入顺序,同时仍允许通过键进行 O(1) 查找。

我的方法如下:

// like unordered_map but keeps the order of the elements for iteration
// implemented as a vector with a unordered_map for constant time lookups
// consider if element removal is needed, since it is O(N) because of the use of a vector of elements
template <typename KEY, typename VAL>
struct ordered_map {
    struct KeyValue {
        KEY key;
        VAL value;
    };

    std::vector<KeyValue> elements; // KeyValue pairs in order of insertion to allow iteration
    std::unordered_map<KEY, int> indexmap; // key -> index map to allow O(1) lookup, is there a way to avoid the redundant key?
    
    //...
}

但是我有一个问题,在我的方法中,我想使用“外部”存储到它的键(在基于映射中的索引值的元素向量中)来查找索引映射。

例如std::sort允许传入一个比较器,但 unordered_sap 似乎没有任何类似的东西。

我真的无法在网上找到有关如何完成此操作的任何信息,但我可能会使用错误的术语进行搜索。

stl 完全支持这种方法吗?

或者我是否需要两次存储 Key ,我想避免这种情况,因为键可以是堆对象,例如 std::strings 。

编辑: unordered_map 而不是 unordered_set 不起作用

我的目标是编写一个 class 像 unordered_map 一样工作,但保持元素的插入顺序,同时仍然允许通过键进行 O(1) 查找

...并且无需复制密钥,以防万一它很大和/或很昂贵。

所以,你想要两件事:

  1. 具有与std::unordered_map相同语义的常量时间关联查找(没有重复的键,或者您会/应该要求std::unordered_multimap
  2. 顺序索引跟踪插入顺序

您已选择使用顺序容器实现关联查找,并使用关联容器实现顺序索引。 我不知道为什么,但让我们尝试更自然的选择:

  1. 关联查找应该只是std::unordered_map<Key, SomeValueType>
  2. 顺序索引可以只是std::vector<SomeValueType*>

剩下的空白是SomeValueType :它可能只是VAL ,但是每当我们删除某些东西时,我们都需要做额外的工作来修复顺序索引。 我们可以改为std::pair<VAL, size_t> ,这样它就可以存储我们需要在擦除时删除的迭代器的索引i 不利的一面是,除了将所有i+1..N个向量元素向下移动一个之外,我们需要更新每个 map 元素的索引值。

如果要保留恒定时间擦除,则可能需要将顺序索引设为std::list<SomeValueType*> ,并在 map 元素中保留std::list::iterator 链表上的实际线性迭代会比向量慢,但在擦除元素时会得到相同的复杂性。


注意。 顺序索引确实需要存储指针而不是迭代器——我最初忘记了无序映射的失效行为。 但是,如果您想访问密钥,它们显然可以是std::unordered_map<key, SomeValueType>::value_type指针......我只是写出了较短的替代方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM