std::multimap和std::vector的混合体?

3
我正在寻找一个类似于 std::multimap 的 STL 容器,但是可以在常量时间内访问任意第 n 个元素。我需要这个容器是因为我在内存中有这样的结构是 std::multimap,由于各种原因,其中存储的项目必须以列表框的形式呈现给用户。由于数据量庞大,我正在使用虚拟项目的列表框(即列表控件轮询第 X 行的值)。
目前,我正在使用额外的 std::vector 来存储 std::map 中的“索引”,并且我像这样填充它:
std::vector<MMap::data_type&> vec;
for (MMap::iterator it = mmap.begin(); it != mmap.end(); ++it)
    vec.push_back((*it).second);

但这并不是一个非常优雅的解决方案。
是否存在某种类似的容器?

1
当然你不会同时在列表框中显示2000万个项目。你如何确定应该在列表框中出现哪些项目? - Ken Bloom
ListCtrl本身会轮询当前屏幕上的项目。这是内置的功能,不是我的代码,但我认为它会计算出在屏幕上可见的项目的矩形。用户可以并且想要滚动查看全部2000万个项目——不要问为什么,这是一个要求。 - Milan Babuškov
顺便说一句,2000万左右是需要支持的最大数量。在大多数情况下,它将在30万到200万之间。 - Milan Babuškov
4个回答

5

我的猜测是我需要在同一个容器中结合序列化和常规索引。然而,当我尝试这样做时,编译器会出现奇怪的错误。这种情况可能吗? - Milan Babuškov
是的,这是可能的:请看这个例子:http://www.boost.org/doc/libs/1_42_0/libs/multi_index/example/sequenced.cpp - James
谢谢大家的回答。不幸的是,我只能接受一个答案,所以这就是了。 - Milan Babuškov

2
那个列表中有多少项,它们的类型是什么,你需要多频繁地在其中插入或删除?根据情况,您可能可以使用排序的 std::vector<std::pair<key,value>>,并使用std::binary_search和一个只比较键的搜索谓词。

项目:最多2000万个,类型为类。如果在中间插入或删除较慢,我可以接受。 - Milan Babuškov
1
@Milan:你确实存储了那个类的对象,还是指针?2000万是很多的,即使这个类很小。你可能需要进行性能分析。为什么不编写自己的STL容器,提供你需要的操作。然后你可以将其实现从std::map+std::vector(你现在拥有的)切换到boost::multi_index::multi_index_containerstd::vector<std::pair<const key,value>>等其他实现,并测量哪个执行效果最好。这也将允许你现在继续前进,以后再回来进行优化。 - sbi
@Matthieu:这和std::map有什么不同吗?就我所知,你现在肯定知道我错过了什么。你能详细解释一下吗? - sbi
问题在于map分配了一个节点,但在重新分配缓冲区或在中间插入时,元素会被重新排序,这就要求元素是可分配的。看看Alexandrescu在其AssocVector中如何处理此问题:http://loki-lib.sourceforge.net/html/a00645.html。我认为你可以在内部使用`std::pair<Key,Value>(以满足要求)和一些reinterpret_cast技巧来使调用者相信类型实际上是std::pair<const Key, Value>` ;) - Matthieu M.
@Milan:如果你这样做,向量中间的插入/删除问题就会变成移动一些内存的问题。我认为这绝对值得尝试使用向量。 - sbi
显示剩余2条评论

1
除了需求之外,从您的评论中看来,您还计划插入/删除项目。我必须承认2000万似乎很多。
现在,我理解轮询的想法,但您是否考虑过像unordered_multimap这样的东西?您可以在O(1)的时间内轮询键,尽管取决于键类型,开销略大。
主要优点是不必处理保持2个容器同步的问题。当然,如果您希望内容排序,则无法使用它。
因此,如果您希望内容排序并快速(不是O(1))访问随机位置,则可以考虑B+树或Radix树。它们的想法是将项目保留在连续的内存区域中,每次仅有几百个。
这只是我脑海中的一部分。如果您想要一个内置解决方案,请考虑自动填充答案 :)

好的,假设它是最多2000万。大多数真实情况将在30万到200万记录范围内。顺便说一下,键是一个字符串。 - Milan Babuškov
对于 std::string,哈希确实会增加一些开销,因此它的时间复杂度为 O(1)。 - Matthieu M.

0

尝试使用hash_multimap。哈希提供大致恒定的时间。Hash_multimap是Visual Studio中的扩展,我相当确定GCC也提供了类似的扩展。如果你非常需要,Boost中也有一些哈希相关的东西。


这如何帮助按键访问需要排序的项目? - sbi
哈希映射将键哈希化。它们还有其他方法来查找吗? - Puppy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接