【发布时间】:2011-01-19 03:34:41
【问题描述】:
对于随机插入和删除,这两者中哪一个更快?
我的猜测是列表。
虽然在集合的情况下将值作为键也很有吸引力。
迭代整个容器的性能是否相似?
【问题讨论】:
标签: c++ list stl containers
对于随机插入和删除,这两者中哪一个更快?
我的猜测是列表。
虽然在集合的情况下将值作为键也很有吸引力。
迭代整个容器的性能是否相似?
【问题讨论】:
标签: c++ list stl containers
首先考虑语义,然后考虑性能。
如果您有一组整数,并且您将整数 6、8、13、8、20、6 和 50 插入其中,您最终将得到一个包含以下五个元素的集合:{ 6, 8, 13, 20, 50 }.
如果您使用列表执行此操作,您最终会得到一个包含以下七个元素的列表:{ 6, 8, 13, 8, 20, 6, 50 }。
那么,你想要什么?用如此不同的语义比较容器的速度是没有意义的。
【讨论】:
列表
设置
【讨论】:
std::hashset 提供集合语义,但没有按顺序遍历。不同的容器适用于不同的使用模式。
如果您关心速度,那么您可能应该使用std::vector。 std::list 每次插入一个元素时都会执行一次堆分配,这通常是一个瓶颈。
一个例外是复制单个项目非常昂贵,或者当您拥有大量项目时。在这些情况下,列表可能会表现得更好,因为它在调整大小时不必移动项目。 std::deque 在这里也是一个不错的选择,但您需要分析您的应用程序才能在两者之间做出决定。
最后,仅当您需要对项目进行排序(或者如果您不想重复项目)时才使用std::set。否则它会比列表或向量慢很多。
【讨论】:
vec.swap(vector<int>());
std::list::splice,您可以避免插入时分配(没有自定义分配器)。
在 std::list 中,插入和删除本身需要 O(1) 的时间,这意味着 非常快,而且最重要的是速度不取决于数量列表中的元素。
在 std::set 中,插入和删除需要花费 O(log(N)) 的时间,这意味着 如果集合中包含很多元素,则速度会稍慢。表达式 O(log(N)) 中的 N 表示元素的数量。 Grosso modo,表示运算所花费的时间与元素个数的对数(底数在这里无关,因为它相当于乘以一个常数,在理论算法分析中忽略)在集合中。
但重要的是要考虑到找到要删除的元素所花费的时间。如果您必须在容器中搜索要删除的元素,这很可能是这种情况,那么 std::list 将花费相当长的时间进行此搜索,这将在 O(N) 中(这意味着 不是快,因为时间与元素的数量成正比,而不是它的对数),而 std::set 将花费 O(log N) 的时间进行搜索。
还要注意,这些理论分析对于元素很少的容器绝对无效,在这种情况下,它们隐藏的乘法常数变得比它关注的时间函数族更重要。
简而言之: std::list => 搜索要删除的元素较慢;更快地删除它。 std::set => 更快地搜索要删除的元素;删除它的速度较慢。
但对于整个操作,以及大量元素,std::set 更好。
您还应该考虑使用哈希表。 Boost、Qt 或 C++0x 中提供了这些的良好实现。他们及时完成所有这些操作,趋向于 O(1)(这意味着 非常非常快)。
【讨论】:
您应该根据实际数据的实际使用情况自行衡量性能。检查典型和最坏情况的性能。
虽然 std::vector 随机插入的时间复杂度为 O(N),std::set O(log(N)) 和 std::list O(1),但 std::vector 在许多情况下表现最好。仅当性能不够重要而无法花时间测量时,才考虑大 O 复杂度。
“如果你不测量你就不是工程”(Rico Mariani)
【讨论】:
std::list 对于插入和删除来说是 O(1)。但是您可能需要 O(n) 才能找到插入或删除点。 std::set 是 O(log(n)) 的插入和删除,它通常实现为红黑树。
考虑找到插入/删除点以做出选择。
【讨论】: