【发布时间】:2010-09-09 04:58:00
【问题描述】:
我对 STL 还很陌生,所以我想知道是否有任何可动态排序的容器?目前我目前的想法是将向量与各种排序算法结合使用,但考虑到将条目插入排序向量的(可能)线性复杂性,我不确定是否有更合适的选择。
为了“动态地”澄清,我正在寻找一个可以在运行时修改排序顺序的容器 - 例如按升序排序,然后再按降序重新排序。
【问题讨论】:
标签: c++ stl containers
我对 STL 还很陌生,所以我想知道是否有任何可动态排序的容器?目前我目前的想法是将向量与各种排序算法结合使用,但考虑到将条目插入排序向量的(可能)线性复杂性,我不确定是否有更合适的选择。
为了“动态地”澄清,我正在寻找一个可以在运行时修改排序顺序的容器 - 例如按升序排序,然后再按降序重新排序。
【问题讨论】:
标签: c++ stl containers
你会想看看 std::map
std::map<keyType, valueType>
地图是根据为keyType提供的
或者
std::set<valueType>
同样按模板参数的
有
std::multiset<valueType>
与 std::set 做同样的事情,但允许相同的元素。
我强烈推荐 Josuttis 的“C++ 标准库”以获取更多信息。它是对 std 库最全面的概述,非常易读,并且充满了晦涩和不那么晦涩的信息。
另外,正如 17 of 26 中提到的,Meyers 的 Effective Stl 值得一读。
【讨论】:
如果您知道要对单个值进行升序和降序排序,那么 set 就是您的朋友。当您想在相反方向“排序”时使用反向迭代器。
如果您的对象很复杂,并且您将根据对象中的成员字段以多种不同的方式进行排序,那么使用向量和排序可能会更好。尝试一次完成所有插入,然后调用一次排序。如果这不可行,那么对于大型对象集合,deque 可能是比向量更好的选择。
我认为,如果您对 级别的优化感兴趣,您最好使用实际数据来分析您的代码。 (这可能是这里任何人都可以给出的最好建议:如果您只在蓝月亮中执行一次,那么在每次插入之后调用 sort 可能并不重要。)
【讨论】:
听起来您想要multi-index container。这允许您创建一个容器并告诉该容器您可能想要遍历其中的项目的各种方式。然后容器会保留多个项目列表,这些列表会在每次插入/删除时更新。
如果你真的想对容器重新排序,你可以在任何std::deque、std::vector,甚至是一个简单的C风格数组上调用std::sort函数。该函数采用可选的第三个参数来确定如何对内容进行排序。
【讨论】:
std::vector 和std::dequeue 没有sort() 方法,只有std::list 有,根据cplusplus.com/reference/stl
stl 没有提供这样的容器。您可以定义自己的,由set/multiset 或vector 支持,但每次排序函数更改时,您都必须重新排序,方法是调用sort(对于vector)或创建一个新集合(用于set/multiset)。
如果您只想从递增排序顺序更改为递减排序顺序,您可以通过调用 rbegin() 和 rend() 而不是 begin() 和 end() 在容器上使用反向迭代器。 vector 和 set/multiset 都是可逆容器,所以这两者都适用。
【讨论】:
std::set 基本上是一个排序容器。
【讨论】:
您绝对应该使用集合/地图。就像 hazzen 所说,你得到 O(log n) 插入/查找。你不会用排序的向量得到这个;您可以使用二分搜索得到 O(log n) 查找,但插入是 O(n),因为插入(或删除)一个项目可能会导致向量中的所有现有项目都被移动。
【讨论】:
事情没那么简单。根据我的经验,插入/删除的使用频率低于查找。排序向量的优点是它占用更少的内存并且对缓存更友好。如果碰巧有与 STL 地图兼容的版本(就像我之前链接的那个),那么很容易来回切换并为每种情况使用最佳容器。
【讨论】:
理论上,关联容器(set、multiset、map、multimap)应该是您的最佳解决方案。
实际上,这取决于您放入的元素的平均数量。 对于少于 100 个元素,向量可能是最好的解决方案,因为: - 避免连续分配-解除分配 - 由于数据局部性,缓存友好 这些优势可能会胜过连续排序。 显然,它还取决于您必须执行多少次插入删除。你要每帧插入/删除吗?
更笼统地说:您说的是性能关键型应用程序吗?
记住不要过早优化...
【讨论】:
答案总是视情况而定。
set 和 multiset 适用于保持项目排序,但通常针对添加、删除和获取的平衡集进行优化。如果您有男子气概的查找操作,那么排序的vector 可能更合适,然后使用lower_bound 查找元素。
此外,您在运行时以不同顺序使用的第二个要求实际上意味着 set 和 multiset 不合适,因为谓词无法在运行时修改。
因此我会推荐一个排序向量。但请记住将与您传递给前一个排序的相同的谓词传递给lower_bound,因为如果您传递了错误的谓词,结果将是未定义的并且很可能是错误的。
【讨论】:
Set 和 multiset 使用底层二叉树;您可以定义
【讨论】:
STL 映射和集合都是排序容器。
我赞同 Doug T 的书籍推荐 - Josuttis STL 书籍是我所见过的最好的学习和参考书。
Effective STL 也是一本学习 STL 内部细节以及应该做什么和不应该做什么的好书。
【讨论】:
对于“STL 兼容”排序向量,请参阅来自 Loki 的 A. Alexandrescu 的 AssocVector。
【讨论】: