【问题标题】:What is the difference between std::set and std::vector?std::set 和 std::vector 有什么区别?
【发布时间】:2023-04-09 11:42:01
【问题描述】:

我现在正在学习 STL。我读到了set 容器。当您想使用set 时,我有疑问?在阅读description of set 之后,它看起来好像没用,因为我们可以用vector 代替它。你能说说vectorset 容器的优缺点吗?谢谢

【问题讨论】:

标签: c++ stl


【解决方案1】:

它们是不同的东西:你决定向量的排序方式,你也可以把尽可能多的相等的东西放入一个向量中。集合根据集合的内部规则进行排序(您可以设置规则,但集合会处理排序),并且您不能将多个相等的项目放入集合中。

当然,您可以维护唯一项的向量,但是当您执行面向集合的操作时,您的性能会受到很大影响。例如,假设您有一组 10000 个项目和一个包含 10000 个不同的无序项目的向量。现在假设您需要检查值 X 是否在集合中的值之间(或在向量中的值之间)。当 X 不在项目中时,搜索向量会慢 100 倍。在计算集合并集和交集时,您会看到类似的性能差异。

总而言之,集合和向量有不同的用途。您可以使用向量而不是集合,但这需要更多的工作,并且可能会严重影响性能。

【讨论】:

  • +1 表示唯一性。我不敢相信没有其他人愿意指出这一点。耻辱!唯一性是主要的好处。并且不要贬低它,但即使是erase/emplace.often 带来的便利也让我使用[unordered_]set,即使理论上它可能会更慢 - 尽管通常在速度无关紧要的设置部分,我'我只担心以后几乎无法阅读代码!例如我想确保将物品放入容器中,但只放入一次;写set.emplace(it) 似乎比写if (vec.find(it) != vec.end() ) { vec.emplace(it) } 好得多(erase 更是如此!)
【解决方案2】:

根据集合搜索项目比向量 (O(log(n)) 与 O(n)) 更快。要根据向量搜索一个项目,您需要迭代向量中的所有项目,但该集合使用红黑树优化搜索,只会查找少数项目以找到匹配项。

集合是有序的,这意味着你只能按顺序从最小的一个到最大的一个,或者相反的顺序。

但是向量是无序的,你可以通过插入顺序来遍历它。

【讨论】:

  • 不正确。您可以在 std::vector 上执行 std::binary_search,它会进行对数比较。
  • 但是二分查找只有在向量排序后才有效。
【解决方案3】:

订购了set。根据您提供的函子,保证保持特定顺序。无论您添加或删除什么元素(除非您添加重复项,这在 set 中是不允许的),它始终是有序的。

vector 完全具有并且您明确给出的顺序。 vector 中的项目是您放置它们的位置。如果你把它们乱序,那么它们就是乱序的;您现在需要 sort 容器将它们按顺序放回原处。

诚然,set 的使用相对有限。通过适当的纪律,可以将项目插入vector 并保持有序。但是,如果您不断地在容器中插入和删除项目,vector 会遇到很多问题。它将执行大量元素的复制/移动等操作,因为它实际上只是一个数组。

将项目插入vector 所需的时间与vector 中已有的项目数成正比。将项目插入set 所需的时间与项目数的 log₂ 成正比。如果项目的数量很大,那将是一个巨大的差异。 log2(100,000) 是 ~16;这是一个重大的速度改进。移除也是如此。

但是,如果您在初始化时一次性完成所有插入操作,则没有问题。您可以将所有内容插入vector,对其进行排序(支付一次),然后使用标准算法对已排序的vectors 查找元素并遍历排序列表。虽然迭代 set 的元素并不是很慢,但迭代 vector 更快。

因此,在某些情况下,排序后的 vector 优于 set。话虽如此,除非您知道有必要,否则您真的不应该为这种优化的费用而烦恼。所以请使用set,除非您对正在编写的系统有经验(因此知道您需要那种性能)或者手头有分析数据告诉您需要vector而不是@987654340 @。

【讨论】:

  • 但是订购的set 不只是一个实现细节吗?从数学上讲,集合没有顺序。
  • @PaulManta:std::set 不是由数学定义的;它由 C++ 规范定义。并且规范声明它是有序的。
  • "所以使用集合,除非..." 嗯.. 使用 Stroupstrup 的建议可能更好:"而且,是的,我的建议是默认使用 std::vector。更一般地,使用连续表示,除非有充分的理由不这样做。”
  • @Alex:在这种情况下,不。如果您正在考虑使用set,那么订单显然对您很重要。保持std::vector 排序需要付出很大的努力。您基本上必须围绕容器构建一个类型。所以我不建议这样做,除非您知道可以获得合法的性能提升。当然,如果您可以访问flat_set,那么是的,几乎没有理由使用常规的set
  • Python 用户的一个陷阱:Python set 是无序的,但 C++ std::set 是有序的。
【解决方案4】:

表格cpluplus.com 设置:

集合是存储遵循特定元素的唯一元素的容器 顺序。

所以集合是有序的并且项目是唯一表示的

而向量:

向量是序列容器,表示可以改变的数组 大小。

所以向量按照你填写的顺序排列,并且可以容纳多个相同的项目

偏好设置:

  • 如果您希望过滤多个相同的值
  • 如果您希望按指定顺序解析项目(在向量中执行此操作需要专门对向量进行排序)。

首选矢量:

  • 如果你想保持相同的值
  • 如果您希望以与推送它们相同的顺序解析项目(假设您不处理向量顺序)

【讨论】:

  • 这是我认为的最佳答案。接受的响应太令人困惑而无法阅读。这就是重点。
【解决方案5】:

简单的区别是 set 只能包含唯一值,并且是排序的。因此,您可以将它用于需要在每次插入/删除后连续对值进行排序的情况。

set<int> a;
vector<int> b;
for (int i = 0; i < 10; ++i)
{
    int val = rand() % 10;
    a.insert(val);
    b.push_back(val);
}
cout << "--SET---\n"; for (auto i : a) cout << i << ","; cout << endl;
cout << "--VEC---\n"; for (auto j : b) cout << j << ","; cout << endl;

输出是

--SET---
0,1,2,4,7,8,9,
--VEC---
1,7,4,0,9,4,8,8,2,4,

【讨论】:

    猜你喜欢
    • 2021-03-23
    • 2021-06-02
    • 2014-03-15
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 2014-07-22
    • 2020-10-16
    相关资源
    最近更新 更多