【发布时间】:2023-04-09 11:42:01
【问题描述】:
我现在正在学习 STL。我读到了set 容器。当您想使用set 时,我有疑问?在阅读description of set 之后,它看起来好像没用,因为我们可以用vector 代替它。你能说说vector 和set 容器的优缺点吗?谢谢
【问题讨论】:
-
既然你读过set,也读过map。然后再次尝试比较!
我现在正在学习 STL。我读到了set 容器。当您想使用set 时,我有疑问?在阅读description of set 之后,它看起来好像没用,因为我们可以用vector 代替它。你能说说vector 和set 容器的优缺点吗?谢谢
【问题讨论】:
它们是不同的东西:你决定向量的排序方式,你也可以把尽可能多的相等的东西放入一个向量中。集合根据集合的内部规则进行排序(您可以设置规则,但集合会处理排序),并且您不能将多个相等的项目放入集合中。
当然,您可以维护唯一项的向量,但是当您执行面向集合的操作时,您的性能会受到很大影响。例如,假设您有一组 10000 个项目和一个包含 10000 个不同的无序项目的向量。现在假设您需要检查值 X 是否在集合中的值之间(或在向量中的值之间)。当 X 不在项目中时,搜索向量会慢 100 倍。在计算集合并集和交集时,您会看到类似的性能差异。
总而言之,集合和向量有不同的用途。您可以使用向量而不是集合,但这需要更多的工作,并且可能会严重影响性能。
【讨论】:
erase/emplace.often 带来的便利也让我使用[unordered_]set,即使理论上它可能会更慢 - 尽管通常在速度无关紧要的设置部分,我'我只担心以后几乎无法阅读代码!例如我想确保将物品放入容器中,但只放入一次;写set.emplace(it) 似乎比写if (vec.find(it) != vec.end() ) { vec.emplace(it) } 好得多(erase 更是如此!)
根据集合搜索项目比向量 (O(log(n)) 与 O(n)) 更快。要根据向量搜索一个项目,您需要迭代向量中的所有项目,但该集合使用红黑树优化搜索,只会查找少数项目以找到匹配项。
集合是有序的,这意味着你只能按顺序从最小的一个到最大的一个,或者相反的顺序。
但是向量是无序的,你可以通过插入顺序来遍历它。
【讨论】:
std::vector 上执行 std::binary_search,它会进行对数比较。
订购了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 不只是一个实现细节吗?从数学上讲,集合没有顺序。
std::set 不是由数学定义的;它由 C++ 规范定义。并且规范声明它是有序的。
set,那么订单显然对您很重要。保持std::vector 排序需要付出很大的努力。您基本上必须围绕容器构建一个类型。所以我不建议这样做,除非您知道可以获得合法的性能提升。当然,如果您可以访问flat_set,那么是的,几乎没有理由使用常规的set。
set 是无序的,但 C++ std::set 是有序的。
表格cpluplus.com 设置:
集合是存储遵循特定元素的唯一元素的容器 顺序。
所以集合是有序的并且项目是唯一表示的
而向量:
向量是序列容器,表示可以改变的数组 大小。
所以向量按照你填写的顺序排列,并且可以容纳多个相同的项目
偏好设置:
首选矢量:
【讨论】:
简单的区别是 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,
【讨论】: