【问题标题】:Why is it so slow to add or remove elements in the middle of a vector?为什么在向量中间添加或删除元素这么慢?
【发布时间】:2013-11-15 05:07:56
【问题描述】:

根据 Accelerated C++:

要使用这种策略,我们需要一种从向量中删除元素的方法。好消息是存在这样的设施。坏消息是从向量中删除元素的速度足够慢,以至于反对将这种方法用于大量输入数据。如果我们处理的数据变得非常大,性能会下降到惊人的程度。

例如,如果我们所有的学生都失败了,我们即将看到的函数的执行时间将与学生人数的平方成正比增长。这意味着对于一个有 100 名学生的班级,该计划的运行时间是一个学生的 10,000 倍。问题是我们的输入记录存储在一个向量中,该向量针对快速随机访问进行了优化。这种优化的一个代价是插入或删除向量末尾以外的元素可能会很昂贵。

作者没有解释为什么向量对于 10,000 多名学生来说会如此缓慢,以及为什么在向量中间添加或删除元素通常很慢。 Stack Overflow 上的人可以为我想出一个漂亮的答案吗?

【问题讨论】:

  • AC++ 是我们推荐的一本好书,所以我严重怀疑他们没有解释什么是向量,什么是不好的,以及为什么。您是否继续阅读以找出答案?
  • @LightnessRacesinOrbit:您在编辑此内容时是否打算删除引用?没有它,问题会更糟。
  • @JohnDibling:意外;抱歉,谢谢

标签: c++ performance vector containers


【解决方案1】:

拿一排房子:如果你把它们建在一条直线上,那么找到 32 号真的很容易:沿着马路走大约 32 间房子的价值,你就在那里。但是添加31号房子就不是那么有趣了。中间——这是一个很大的建设项目,对丈夫/妻子和孩子的生活造成了很大的干扰。在最坏的情况下,无论如何,道路上都没有足够的空间容纳另一所房子,因此您必须在开始之前将所有房子搬到另一条街道上。

同样,向量连续地存储它们的数据,即在内存中连续的、连续的块中。

这对于快速找到 nth 元素非常有用(因为您只需沿着 n 位置移动并取消引用),但是插入中间非常糟糕,因为您必须一次一个地移动所有后面的元素。

其他容器被设计成易于插入元素,但代价是它们因此不太容易在其中找到东西。没有适合所有操作的容器。

【讨论】:

  • 这是一个很好的答案,它完美地回答了我所有的思考。很抱歉这么快就选择了最佳答案,这真是太棒了:) 谢谢你帮助我,Stackoverflow!你们都很棒。
【解决方案2】:

std::vector<T>中间插入元素或从中移除元素时,修改点之后的所有元素都需要移动:插入时需要向后移动,移除时需要向前移动关闭差距。背景是std::vector<T>基本上只是一个连续的元素序列。

虽然这个操作对于某些类型来说并不算太糟糕,但它可能会变得相对较慢。但是请注意,容器的大小需要有一些合理的大小,否则移动的成本会很大:对于小向量,插入/从中删除可能比使用其他数据结构(例如列表)更快。然而,最终维护更复杂结构的成本确实得到了回报。

【讨论】:

    【解决方案3】:

    std::vector 将内存分配为一个范围。如果您需要在扩展的中间插入一个元素,您必须向右移动向量的所有元素,以创建一个空闲槽,您将在其中插入新元素。此外,如果 extend 已经充满了元素,则 vector 需要分配一个新的更大的 extend 并将所有元素从原始 extent 复制到新的 extent。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-19
      • 1970-01-01
      • 2013-06-21
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多