维护Ordered的对象集合

时间:2011-01-24 01:46:55

标签: c++ collections dynamic html-lists

我对一组对象有以下要求:

  • 动态尺寸(理论上无限制,但实际上有几千个应该绰绰有余)
  • 有序,但允许在任意位置重新排序和插入。
  • 允许删除
  • 索引访问 - 随机访问
  • 计数

我存储的对象不大,有几个属性,有一两个小数组(256个布尔值)

在编写链表之前,是否有我应该知道的内置类?

3 个答案:

答案 0 :(得分:5)

原始答案:这听起来像标准库中的std::list(双向链表)。

新答案: 更改规范后,std::vector可能会有效,只要不超过几千个元素,并且矢量中间没有大量的插入和删除。中间插入和删除的线性复杂度可能被矢量运算的低常数所抵消。如果您在开始和结束时进行了大量插入和删除操作,std::deque也可以正常工作。

答案 1 :(得分:1)

您没有指定足够的要求来选择最佳容器。

  

动态尺寸(理论上无限制,但实际上有几千个应该绰绰有余)

STL容器旨在根据需要增长。

  

有序,但允许在任意位置重新排序和插入。

允许重新订购? std :: map无法重新排序:您可以从一个std :: map中删除并使用不同的顺序插入另一个,但作为不同的模板实例,这两个变量将具有不同的类型。 std :: list有一个sort()成员函数[感谢Blastfurnace指出这一点],对大型对象特别有效。使用非成员std::sort()函数可以轻松使用std :: vector,对于微小对象尤其有效。

可以在地图或列表中完成在任意位置的高效插入,但您如何找到这些位置?在列表中,搜索是线性的(您必须从您已经知道的某个地方开始,逐个元素地向前或向后扫描)。 std :: map提供了有效的搜索,就像已经排序的向量一样,但插入向量涉及移动(复制)所有后续元素以产生空间:这在事物的方案中是一个代价高昂的操作。

  

允许删除

所有容器都允许删除,但是你有与插入时完全相同的效率问题(例如,如果您已经知道位置,则快速列表,地图快速,矢量删除速度慢,尽管您可以“标记“删除元素而不删除它们,例如使字符串为空,在结构中有一个布尔标志。”

  

索引访问 - 随机访问

向量以数字方式索引(但可以二进制搜索),通过任意键(但没有数字索引)进行映射。 list未编入索引,必须从已知元素进行线性搜索。

  

计数

std::list提供O(n)size()函数(以便它可以提供O(1)拼接),但您可以自己轻松跟踪大小(假设您不会拼接)。其他STL容器已经有{(1)}的O(1)时间。

结论

考虑使用std :: list是否会导致对所需元素进行大量低效的线性搜索。如果没有,那么列表确实可以为您提供有效的插入和删除。度假很好。

地图或哈希地图将允许快速查找和轻松插入/删除,无法使用,但您可以使用其他排序标准轻松地将数据移出到另一个地图(效率适中。

矢量允许快速搜索和就地求助,但最差的插入/删除。使用元素索引进行随机访问查找速度最快。

答案 2 :(得分:1)

- 插入和删除:这对任何STL容器都是可能的,但问题是它需要多长时间。任何链表容器(list,map,set)都会在恒定时间内完成此操作,而类似数组的容器(vector)将在线性时间内完成(使用常量分摊的分配)。

-Sorting:考虑到你可以随时保留一个已排序的集合,这不是什么大问题,任何STL容器都会允许这样做。对于地图和集合,您无需执行任何操作,他们已经始终保持对集合进行排序。对于矢量或列表,您必须完成这项工作,即您必须对新元素所在的位置进行二进制搜索并将其插入其中(但STL算法具有您需要的所有部分)。

-Resorting:如果您需要获取当前集合,您已根据规则A进行排序,并根据规则B使用该集合,这可能是一个问题。通过排序规则对映射和集合等容器进行参数化(作为类型),这意味着要使用它,您必须从原始集合中提取每个元素,并将它们插入到具有新排序规则的新集合中。但是,如果您使用向量容器,则可以随时使用STL排序函数来使用您喜欢的任何规则。

-Random Access:你说你需要随机访问。就个人而言,我对随机访问的定义意味着可以在恒定时间内(通过索引)访问集合中的任何元素。使用该定义(我认为这是非常标准的),任何链表实现都不符合条件,它使您只能使用类似数组的容器(例如std :: vector)。

结论,拥有所有这些属性,最好使用std :: vector并实现自己的排序插入和排序删除(对向量执行二进制搜索以找到要删除的元素或要插入的位置新元素)。如果您需要存储的对象具有相当大的尺寸,并且对它们进行排序的数据(名称,ID等)很小,您可以考虑通过保持未排序的对象链接列表来拆分问题(完整信息)并保持键的排序向量以及指向链表中相应节点的指针(在这种情况下,当然,前者使用std :: list,后者使用std :: vector)。

顺便说一句,我不是STL容器的专家,所以我可能在上面做错了,只要自己想一想。为自己探索STL,我相信你会找到你需要的东西,或者至少你需要的所有东西。也许,看看Boost图书馆。