其他分享
首页 > 其他分享> > c-std :: unordered_map-如何随时“跟踪”最大/最小键

c-std :: unordered_map-如何随时“跟踪”最大/最小键

作者:互联网

我有std :: unordered_map< int,int>.
我不想使用其他结构(例如树)或其他导致延迟要求的结构.
但是在任何时候我都需要知道当前的最大键和最小键.
我怎样才能做到这一点?分布不均匀,而是经常删除和插入max和min.因此,我需要比“仅在删除当前最大/最小时扫描整个地图以获取新的最大/最小”更聪明的方法.

我不想使用任何其他结构.我想使用std :: unordered_map!

upd根据答案创建了这样的结构:

struct OrderBookItem {
    int64_t price;
    int32_t lots;
};

typedef multi_index_container
    <OrderBookItem, indexed_by<

    hashed_unique<
    BOOST_MULTI_INDEX_MEMBER(OrderBookItem,int64_t,price)
    >,

    ordered_unique<
    BOOST_MULTI_INDEX_MEMBER(OrderBookItem,int64_t,price),
    std::greater<int64_t>
    >

    >> OrderBookContainer;

解决方法:

无法满足您的确切要求:std :: unordered_map快速(即O(1)插入/擦除/查找),因为它不对元素进行排序.这意味着找到最小值/最大值需要O(N).

std :: map支付的订购价格使插入/删除/查找(包括找到最小值/最大值)全部变为O(log N).

如果您不介意使用Boost,可以看一下Boost.MultiIndex库.这使您可以同时通过多个接口访问数据.它是一个用途非常广泛的高性能库,也可以用于MRU缓存数据结构(它还结合了快速访问和对订单的跟踪).

您的主要std :: unordered_map接口由hashed_unique索引提供,您可以在其中使用标识函数对象(由Boost.MultiIndex提供).您的辅助接口将模仿std :: set.这样可以在O(1)时间内找到* begin()和* rbegin()的最小值/最大值.

您可以通过在用户定义的MyOrder函数对象中添加ordered_unique索引来计算您想要用来对它们进行排序的任何条件.小代码示例(在各处省略boost ::名称空间)

using MyContainer = multi_index_container<
    Item,
    indexed_by<
        hashed_unique<identity<Item>>, // O(1) erasure/lookup, O(log N) insertion
        ordered_unique<MyOrder<Item>>  // track minimum/maximum in O(log N)
    >
>;

在后台,Boost.MultiIndex大致将其实现为std :: set< Value>使用std :: unordered_map< Key,设置< Value> :: iterator>.这意味着查找和擦除均为O(1).擦除可以为O(1),因为unordered_map :: erase(value)将迭代器返回到set中,而std :: set< Value> :: erase(iterator)为O(1).

但是,插入仍为O(log N),因为您无法避免在更短的时间内找到有序序列中新插入值的等级.

与用于查找/擦除的std :: map相比,此改进仅花费了每个元素空间开销几个指针.

标签:unordered-map,c,c11,boost,boost-multi-index
来源: https://codeday.me/bug/20191009/1882064.html