std :: set和std :: vector有什么区别?


Answers:


98

Aset被订购。这是保证留在一个特定的顺序,根据算符您提供。无论您添加或删除什么元素(除非您添加重复项,都不允许在其中进行重复set),它始终是有序的。

Avector具有并且只有您显式给出的顺序。中的项目vector是您放置它们的地方。如果您将它们乱序放置,则说明它们乱七八糟。您现在需要sort将容器放回原处。

诚然,set具有相对有限的用途。只要遵守适当的纪律,就可以将物品插入vector并保持有序。但是,如果您不停地从容器中插入和取出物品,vector将会遇到很多问题。因为它实际上只是一个数组,所以它将进行很多元素的复制/移动等等。

将项目插入中所需的时间vector与中已存在的项目数成正比vector。将项目插入到a中set所花费的时间与log2成正比与项目数。如果项目数量很大,那就有很大的不同。log 2(100,000)为〜16;这是一个重大的速度改进。删除也一样。

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

因此,在某些情况下,排序vector优于set。话虽如此,除非您知道这样做是必要的,否则您真的不应该为这种优化而费心。因此,set除非您对正在编写的系统类型有经验(因此知道您需要这种性能)或手头有可能需要avector而不是a的分析数据,否则请使用a set


5
但是set订购不仅是实施细节吗?从数学上讲,集合没有顺序。
保罗·曼塔

44
@PaulManta:Astd::set不是由数学定义的;它是由C ++规范定义的。并且规范指出它是有序的。
Nicol Bolas

2
“所以请使用一个集合,除非...”嗯。使用Stroupstrup的建议可能更好:“是的,我的建议是默认使用std :: vector。更一般地,除非有充分的理由,否则使用连续表示不。”

1
@Alex:在这种情况下,不会。如果您正在考虑使用set,那么订单对您显然很重要。保持std::vector排序需要大量的精力。基本上,您必须围绕容器构建一个类型。因此,除非您知道要获得合理的性能提升,否则我不建议您这样做。当然,如果您可以访问flat_set,则可以,几乎没有理由使用normal set
Nicol Bolas

3
Python用户的一个陷阱:Pythonset是无序的,但是C ++std::set是有序的。
liberforce

12

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

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

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


6
+1代表唯一性。我不敢相信没有人会指出这一点。耻辱!唯一性是主要好处。而不是贬低它,但即使erase/伴随的轻松性也emplace常常使我使用[unordered_]set,即使它在理论上可能比较慢-尽管通常在不关心速度的设置部分中,我只担心几乎不能稍后阅读代码!例如,我想确保将物品放入容器中,但只能放入一次;它似乎远更好写的set.emplace(it)if (vec.find(it) != vec.end() ) { vec.emplace(it) }(多仍然erase!)
underscore_d

7

形式cpluplus.com 设置为:

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

因此该集合是有序的,并且项是唯一表示的

而vect:

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

所以向量按您填充的顺序排列,可以容纳多个相同的项目

首选设置:

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

首选矢量:

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

我认为这是最好的答案。接受的响应太混乱了,难以阅读。这就是重点。
Sriram Murali

6

与向量相比(O(log(n))vs O(n)),针对集合搜索项目的速度更快。要针对向量搜索项目,您需要迭代向量中的所有项目,但是集合使用红黑树来优化搜索,将只寻找几个项目来查找匹配项。

该集合是有序的,这意味着您只能按顺序或相反的顺序将其从最小的一个迭代到最大的一个。

但是向量是无序的,您可以按插入顺序对其进行移动。


1
不对。你可以做std::binary_search一个std::vector,这确实比较对数数。
阿伦

29
但是,只有对向量进行排序后,二进制搜索才有效。
rsaxvc 2012年

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,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.