【问题标题】:key-value data structure to search key in O(1) and get Max value in O(1)键值数据结构在 O(1) 中搜索键并在 O(1) 中获取最大值
【发布时间】:2013-01-23 00:33:32
【问题描述】:

我需要实现一个键值数据结构,在 O(lgn) 或 O(1) 中搜索唯一的 key 并在 O( 1)。我在考虑

boost::bimap< unordered_set_of<key> ,multiset_of<value> >

请注意,我的键值数据集中没有重复键。但是,两个键可能具有相同的值。因此我使用 multiset 来存储值。

我需要经常插入/删除/更新键值对

听起来怎么样?

【问题讨论】:

  • 您也可以考虑将哈希表与最大堆并行,这并不是真正的 STL 特定建议,但也许有用。
  • 如果你不需要删除元素(你没有提到这个问题)一个带有std::map/std::unordered_map 的简单类并在插入时检查最大值就可以了。 @acjohnson55 的最大堆解决方案适用于您需要删除元素时。 bimap 做的比你想要的多,因此它有点慢,但你不必编写一个字节,你得到一个经过良好测试的解决方案,所以听起来相当不错!
  • ooor,只是一个 std::map + 一个迭代器到最后。 boost::bimap 可能是矫枉过正
  • @Csq 我确实需要经常删除元素。事实上,我将从最大堆顶部删除具有最大值的元素。因此,我认为您的解决方案不适合我。你怎么看?
  • @MooingDuck 为什么有点矫枉过正?

标签: c++ boost data-structures stl bimap


【解决方案1】:

这取决于你想做什么。所以很明显,您希望将它用于一些 get-the-maximum-values-in-an-iteration 构造。

问题 1:您是否也通过它们的访问元素?

  • 如果,我可以为您想出两个解决方案:

    1. 使用 boost::bimap - 具有对数运行时间的简单、经过测试的解决方案。

    2. 创建一个自定义容器,其中包含一个std::map(或者更快地通过键访问std::unordered_map)和一个堆实现(例如std::priority_queue&lt;std::map&lt;key, value&gt;::iterator&gt; + 自定义比较器),使它们保持同步等。这是困难的方式,但也许更快。两者上的大多数操作都是 O(logn)(插入、get&pop max、按键获取、删除),但常数有时很重要。虽然是你使用std::unordered_map,但按键操作的访问将是 O(1)。

      您可能还想为新容器编写测试,并针对您最常使用的操作对其进行优化。

  • 如果,你真的只是使用使用最大值的元素访问

    问题2:你是随机插入/删除/更新元素,还是先将所有元素放入一轮,然后逐个删除?

    • 对于随机插入/删除/更新,请使用std::priority_queue&lt;std::pair&lt;value, key&gt;&gt;

    • 如果先放入元素,然后逐个删除,请在第一次删除操作之前使用 std::vector&lt;std::pair&lt;value, key&gt;&gt;std::sort() 。不要实际删除元素,只需对其进行迭代。

【讨论】:

  • 感谢您的回答,是的,我确实需要通过它们的键访问元素。因此,您的 boost::bimap 解决方案对我有好处。
【解决方案2】:

您可以使用std::mapstd::set 来构建它。

  1. 保存实际值的映射,即std::map&lt;key, value&gt; m;。这是存储您的值的地方。将元素插入地图是 O(log n)。

  2. 一组指向地图的迭代器;该集合按相应映射条目的值排序,即std::set&lt;std::map&lt;key, value&gt;::iterator, CompareBySecondField&gt; s;,类似于(未经测试):

    template <class It>
    struct CompareBySecondField : std::binary_function<It, It, bool> {
        bool operator() ( const T &lhs, const T &rhs ) const {
            return lhs->second > rhs->second;
        }
    };
    

    然后,您可以使用 *s.begin(); 获取具有最大值的映射条目的迭代器。

这很容易构建,但您必须确保在添加/删除元素时更新两个容器。

【讨论】:

    猜你喜欢
    • 2018-12-04
    • 2019-01-14
    • 1970-01-01
    • 2012-05-13
    • 2011-08-26
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    相关资源
    最近更新 更多