std :: map具有高效的第n个元素访问权限

时间:2011-01-14 00:42:21

标签: c++ data-structures

我有一组数据需要存储在有序地图中(即按键有效插入,删除和定位项目),但我还需要能够找到 nth < / em>元素没有遍历整个地图(有时可能会有成千上万的项目)。

我知道一种方法:使用红色/黑色树,但也要保留每个节点的一条腿上的子项目总数。它使插入和删除速度变慢(因为你必须像沿着路径更新路径上每个节点的计数),但你可以找到任何 n nth 元素>与寻找钥匙大致相同。

我想知道是否存在我可以使用的这种事物的现有C ++实现。如果没有,我可以自己写,但我真的不愿意。


编辑:我对用例有一些澄清。我稍微误解了一下:按键查找项目后,他们需要能够有效地找出找到的项目的索引,才能正确显示滚动条。

是合法的需求,我上面描述的数据结构仍然适用于它,所以我仍在寻找答案。但是,由于似乎还没有人提出一个,我将开始自己编码。

9 个答案:

答案 0 :(得分:3)

如果您使用修改后的Trie,其中非终端节点跟踪其下方有多少终端节点,您可以快速有序查找。

答案 1 :(得分:3)

考虑到类似的问题,这是我对其他问题的回答。

associative / random access container

我想这可能也适用于你的问题。


我一直在寻找这样的数据结构。

最近,我发现了一个非常有前途的库,它具有您正在寻找的所有功能。

在O(log n)中查看带有随机访问的cntree :: set。

这是链接。 http://dl.dropbox.com/u/8437476/works/countertree/index.html

虽然它似乎正在开发中,但我发现它非常实用。

答案 2 :(得分:2)

我从未使用boost::multi_index_container<>,但听起来它可能有能力做你想要的(尽管我不太确定 - 乍一看这是一个相当复杂的库)。

它有一个随机访问密钥类型,但我不确定如何以保持插入元素的索引与其他索引的顺序同步的方式更新随机索引。 另请注意tutorial on using a random index中的以下内容:

  

这种增加的灵活性是有代价的:在索引末尾以外的位置处的插入和删除具有线性复杂性,而这些操作对于有序索引是恒定的时间。这种情况让人联想到std :: list和std :: vector之间复杂性行为的差异:在随机访问索引的情况下,插入和删除从不会导致任何元素复制,因此这些操作的实际性能是可以接受的尽管在顺序指数方面存在理论上的缺点。

我不清楚这对你是否是一个交易杀手,即使你可以设法按照你想要的方式同步插入元素的随机索引。

答案 3 :(得分:0)

一种选择是开发一个基于std :: vector的容器,但也有一个map接口。它将存储一个单独的散列表或二进制树,它使用元素的键来访问它们,但实际值将是指向向量使用的内部数组的指针。

这样的怪物可能看起来毫无意义,容易出错,或者某些人的设计气味,但这样的数据结构确实有它的位置。我已经看到这在零售系统中的硬件驱动程序的代码中使用,其中容器的两个用户需要以不同的方式访问它。当使用“因为它在那里”这是一件坏事,但如果使用得当它是一种救星。

答案 4 :(得分:0)

愚蠢的想法:还要通过O(log n)插入和随机访问将密钥保留在indexed skip list中。参见http://cglab.ca/~morin/teaching/5408/refs/p90b.pdf

这比使用order statistic trees效率更高,并且需要更多空间和簿记功能。

另请参阅:Rank Tree in C++

答案 5 :(得分:0)

签出boost::container::flat_map [1] ,它是基于类似矢量的容器 [2] 的地图。

使用底层的随机访问迭代器,您将获得O(1)查找; nth [3] 成员函数可帮助您获得第n个元素的迭代器。


[1] Boost.Container
[2] Documentation on flat_map
[3] boost::container::flat_map::nth

答案 6 :(得分:-1)

晚会(在寻找相关内容时点击此问题) - 但是这里的排序向量是否适合用例? 插入时间更长 - 除非您在排序之前在一个批次中完成大部分/全部插入操作。 在那之后,查找时间实际上可以超过std :: map - 并且获取索引是微不足道的。

答案 7 :(得分:-2)

尝试使用有序的std :: list并使用std :: binary_search进行搜索。可以使用std :: list并使用std :: lower_bound插入节点来实现有序列表。网上和SO上有很多这方面的例子。

答案 8 :(得分:-2)

由红黑树支持的MS VC STL地图。

我认为不可能在同一数据结构中进行有效的搜索(通过密钥)和有效的随机访问。

如果有效的随机访问非常重要,那么将数据存储在类似矢量的随机访问容器中会更好。可以使用其他索引完成排序和密钥搜索。 RDBMS就是这样做的。

或者,如果插入/删除更重要,那么为随机访问管理诸如键数组(或行号索引)之类的内容似乎是可以避免的。