C++ C++;列表与集合

C++ C++;列表与集合,c++,list,stl,containers,C++,List,Stl,Containers,对于随机插入和删除,这两种方法中哪一种更快 我猜是名单 尽管在集合的情况下,将值作为键也是很有吸引力的 对整个容器进行迭代的性能类似吗?std::list对于插入和删除是O(1)。但是您可能需要O(n)来找到插入点或删除点。对于插入和删除,set是O(log(n)),它通常实现为红黑树 考虑一下如何找到插入/删除点来做出选择。首先考虑语义,然后考虑性能 如果您有一组整数,并在其中插入整数6、8、13、8、20、6和50,那么最终将得到一个包含以下五个元素的集合:{6、8、13、20、50}。 如

对于随机插入和删除,这两种方法中哪一种更快

我猜是名单

尽管在集合的情况下,将值作为键也是很有吸引力的

对整个容器进行迭代的性能类似吗?

std::list对于插入和删除是O(1)。但是您可能需要O(n)来找到插入点或删除点。对于插入和删除,set是O(log(n)),它通常实现为红黑树


考虑一下如何找到插入/删除点来做出选择。

首先考虑语义,然后考虑性能

如果您有一组整数,并在其中插入整数6、8、13、8、20、6和50,那么最终将得到一个包含以下五个元素的集合:
{6、8、13、20、50}。

如果你用一个列表来做这件事,你会得到一个包含以下七个元素的列表:
{6,8,13,8,20,6,50}


那么,你想要什么?比较具有如此不同语义的容器的速度是没有意义的。

如果您关心速度,那么您可能应该使用
std::vector
<代码>标准::列表在每次插入元素时执行一次堆分配,这通常是一个瓶颈

一个例外是当单个项目非常昂贵的复制,或当你有一个可怕的很多他们。在这些情况下,列表的性能可能会更好,因为它在调整大小时不必移动项目。在这里,std::deque也是一个不错的选择,但是您需要对应用程序进行概要分析,以便在两者之间做出选择


最后,仅当您需要对项目进行排序(或者不希望重复项目)时,才使用
std::set
。否则,它将比列表或向量慢得多。

您应该根据实际数据的实际使用情况来衡量性能。检查典型和最坏情况下的性能

虽然std::vector对于随机插入、std::set O(log(N))和std::list O(1)具有O(N)时间复杂度,但std::vector在许多情况下表现最好。只有当性能不够重要,不需要花时间进行测量时,才考虑大O复杂性

“如果你不测量,你就不是工程师”(Rico Mariani)

列表

  • 搜索(线性时间)
  • 插入、删除、移动(需要固定时间)
  • 元素可以是有序的
  • 可以对元素进行排序
  • 元素可能是重复的
  • 设置

  • 搜索(大小为对数)
  • 插入和删除(通常为对数)
  • 元素是无序的
  • 元素总是从低到高排序
  • 元素是独一无二的

  • 在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)(这意味着非常快)。

    就我的目的而言,这两种方法都会起作用。-无论如何,我觉得我更喜欢列表。谢谢如果两者都起作用,那么你是说顺序无关紧要。这实际上是一个集合的一个点,而不是列表的一个点。你不应该根据你喜欢的东西来选择一个容器:它们在界面上都非常相似,所以如果你喜欢其中一个,那么你几乎对它们都很满意。谢谢!所以你能说如果我能接受集合的语义,它很可能比列表更快吗?或者我误解了O(log(n))?我说不出来,您没有指定如何访问列表以查找插入/删除点。如果你已经有了一个迭代器,而且恰好在正确的位置,那么O(1)是不可能被打败的。std::set还有其他的优点,比如如果你不想在集合中出现重复的话,我可以使用一个带有预分配内存的列表。(使用自定义分配器)。我对vector最大的担忧是在随机位置删除,因为我害怕每次这样做时它都会重新分配整个数组。这是一个问题吗?@mokaschitta:我的理解是,当向量增长时,当你删除元素,甚至清除整个数组时,它们会保留分配给它们的内存。我不知道这个行为是标准强制的,还是典型的实现方式(我是sur