我有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;
答案 0 :(得分:7)
无法满足您的确切要求:std::unordered_map
速度很快(即O(1)
插入/删除/查找),因为它没有对其元素进行排序。这意味着找到最小值/最大值需要O(N)
。
std::map
支付的订购价格(插入/删除/查找(包括查找最小/最大))全部变为O(log N)
。
如果您不介意使用Boost,可以查看Boost.MultiIndex库。这允许您同时通过多个接口访问您的数据。它是一个极其通用和高性能的库,也可用于MRU缓存数据结构(它还结合了快速访问和订购跟踪)。
您的主std::unordered_map
接口由hashed_unique
索引提供,您可以在其中使用identity
函数对象(由Boost.MultiIndex提供)。您的辅助界面将模仿std::set
。这允许在O(1)
时间内找到*begin()
和*rbegin()
的最小/最大值。
您可以通过添加ordered_unique
索引和用户定义的MyOrder
函数对象来计算您想要用来订购它们的标准。小代码示例(到处省略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, set<Value>::iterator>
。这意味着查找和删除都是O(1)
。擦除可以是O(1)
,因为unordered_map::erase(value)
将迭代器返回到set
,std::set<Value>::erase(iterator)
是O(1)
。
但是,插入仍为O(log N)
,因为您无法避免在更短的时间内找到有序序列中新插入值的等级。
与std::map
相比,查找/擦除成本每个元素空间开销只有几个指针。
答案 1 :(得分:-1)
你可以写一个包装器。这样,您可以获得每次插入/删除并保留最小/最大值。
#pragma once
#include <unordered_map>
using std::unordered_map;
class my_unordered_map
{
public:
void insert(int key, int value)
{
_map[key] = value;
if (_max < value)
_max = value;
if (_min> value)
_min = value;
}
int get(int key)
{
auto it = _map.find(key);
if (it != _map.end())
return it->second;
return 0; // or some error handling here.
}
int getMin()
{
return _min;
}
int getMax()
{
return _max;
}
// more functionality here.
private:
unordered_map<int, int> _map;
int _min = 0;
int _max = 0;
};