c++向量和列表插入

C++ vector and list insertion

本文关键字:插入 列表 向量 c++      更新时间:2023-10-16

有人知道为什么在列表中间插入一个元素会更快吗比在向量中间插入一个元素更容易?

我更喜欢使用向量,但被告知如果可以的话使用列表。有人能解释为什么吗?是不是总是推荐用list over vector?

如果我逐字回答问题,找到数组(std::vector)的中间是一个简单的操作,您将长度除以2,然后向上或向下四舍五入以获得索引。查找双链表(std::list)的中间需要遍历所有元素。即使你知道它的大小,你仍然需要遍历一半的元素。因此std::vector比std::list快,换句话说,一个是O(1),另一个是O(n)。

在已知位置插入需要对数组的相邻元素进行洗牌,并且只需在双链表中链接另一个节点,正如其他人在这里解释的那样。因此,具有O(1)的std::list比具有O(n)的std::vector要快。

加在一起,为了精确地插入到中间位置,数组有O(1) + O(n),双链表有O(n) + O(1),这使得在中间插入两个容器类型都是O(n)。所有这些都忽略了CPU缓存和分配器速度,它只是比较了"简单"操作的数量。总之,您需要了解如何使用容器。如果您确实经常在随机位置插入/删除,std::list可能更好。如果很少这样做,并且只读取容器,则std::vector可能更好。如果你只有10个元素,那么所有的0 (x)可能都是毫无价值的,你应该选择你最喜欢的那个。

插入到vector的中间需要将插入点之后的所有元素洗牌以腾出空间,这可能涉及大量复制。

这个列表被实现为一个链表,每个节点占用自己的内存空间,引用相邻节点,所以添加一个新节点只需要修改2个引用指向新节点。

根据所使用的数据类型,vector可能比list执行得快得多。但是要复制的对象越复杂,vector的效果就越差。

简单来说,vector就是数组。因此,它的元素存储在连续的内存位置(即,一个紧挨着另一个)。唯一的例外是vector允许在运行时调整大小,而不会导致数据丢失。

现在,要插入到列表中,您需要识别节点,然后创建新元素(在内存中的任何位置),存储值并连接指针。

但是在vector (array)的情况下,必须物理地将元素从一个单元格移动到另一个单元格,以便为新元素创建空间。这种物理移动是导致延迟的原因,特别是在需要移动许多元素(即数据)的情况下。你没有物理地移动数组元素。

Ulrich Eckhardt的回答非常好。我没有足够的声誉来添加评论,所以我将自己写一个答案。就像乌尔里希说的,从理论上讲,链表和向量在中间的插入速度都是O(n)在实践中,现代cpu有一个叫做"预取器"的东西。它很擅长获取连续数据。由于vector在内存中是连续的,由于预取器的存在,移动大量元素的速度非常快。你需要操作非常非常大的向量为了让它们的插入速度比列表慢。要了解更多细节,请查看这篇很棒的博客文章:

http://gameprogrammingpatterns.com/data-locality.html