为什么std::vector::insert复杂度是线性的(而不是常量)

Why is std::vector::insert complexity linear (instead of being constant)?

本文关键字:常量 线性 vector insert 复杂度 为什么 std      更新时间:2023-10-16

假设我在大小为'n'的std::vector<mytype>的第I个位置插入p个新元素。

由于std::vector中的项保证为其元素使用连续的存储位置,因此看起来这将花费我4个步骤来完成上述操作:

1)如果我们没有空间,可能会重新分配向量,基本上是将其大小加倍。但这是一个常数时间操作(尽管是一个非常大的操作)。

2)接下来是一个从索引0到索引i-1的从旧向量到新向量的元内存。

3)然后复制'p'新条目插入到索引。

4)然后为从旧向量到新向量从i+1到n个索引的所有项创建另一个memcpy。

不都是常数时间操作吗?那么插入本身不应该是一个常数时间操作吗?那么为什么std::vector::insert对插入的元素数量(复制/移动构造)加上位置(移动)后的元素数量是线性的?

不都是常数时间操作吗?

不,memcpymemmove的时间复杂度在被复制或移动的块的大小上是线性的,因为每个被移动的k字节都需要被精确地触摸一次。被移动的块的大小是sizeof(T) * N,使得时间也是线性的。

即使在vector的末尾添加一个元素也具有线性复杂性,因为在重新分配时复制数据(然而,在vector的末尾添加N元素具有平摊线性复杂性,即每项平摊常数复杂度)。

您提到可能会有重新分配,那么在这种情况下,时间复杂度显然将是线性,正如上面的答案所述。但是,即使没有重新分配,时间复杂度也将线性,因为vector::insert()函数的复杂度为O(n+m),其中n为插入的元素数m为移动的元素数

示例:假设我们在vector前面插入一个元素,那么vector中存在的所有元素都将向右移动(这需要线性时间),以便将元素插入到前面。时间复杂度为0 (1 + elements_in_vector)