简体   繁体   English

删除向量和双端队列中的项目的时间复杂度

[英]Time complexity of removing items in vectors and deque

I have read that time complexity of adding items to end of a std::vector is amortized constant and inserting items at the top and bottom of a std::deque is constant.Since both these containers have a random access iterator thus accessing elements at any index is constant. 我已经读过,在std::vector末尾添加项目的时间复杂度是分摊常量,并且在std::deque的顶部和底部插入项目是常量。因为这两个容器都有一个随机访问迭代器,因此访问元素任何指数都是不变的。 Please let me know if I have any of these facts wrong.My question is if accessing an element in a std::vector or std::deque is constant then why is the time complexity of removing an element via erase O(n). 如果我有任何这些事实错误,请告诉我。我的问题是,如果访问std::vectorstd::deque的元素是常量,那么为什么通过擦除O(n)删除元素的时间复杂度。 One of the answers here here states that removing elements via erase is O(n). 这里的答案之一指出通过擦除元素是O(n)。 I know that erase removes the elements between the starting iterators and the ending one so does the answer basically mean that its O(n) depending on the no of elements between the two iterators and that removing a single element from a vector/deque in any index will be zero? 我知道擦除会删除起始迭代器和结束迭代器之间的元素,所以答案基本上意味着它的O(n)取决于两个迭代器之间的元素的数量,并且从任何向量/双端队列中删除单个元素指数会为零?

The things are a bit different for std::vector and std::deque , as well as they are different for C++98 and C++11. std::vectorstd::deque情况有所不同,C ++ 98和C ++ 11也有所不同。

std::vector 的std ::矢量

The complexity of std::vector::erase() is linear both to the length of the range erased and to the number of elements between the end of the range and the end of the container (so erasing an element from the end takes constant time). std::vector::erase()的复杂性与std::vector::erase()范围的长度以及范围的结尾和容器的末尾之间的元素数量是线性的(因此从末尾擦除元素需要不变时间)。

C++2003 [lib.vector.modifiers] reads: C ++ 2003 [lib.vector.modifiers]读取:

iterator erase(iterator position);
iterator erase(iterator first, iterator last);`

... ...

Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements. 复杂性: T的析构函数被称为等于被擦除元素数量的次数,但T赋值运算符被称为等于擦除元素之后的向量中元素数量的次数。

C++14 draft N4140 [vector.modifiers] reads: C ++ 14草案N4140 [vector.modifiers]读取:

Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the move assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements. 复杂性: T的析构函数被称为等于被擦除元素数量的次数,但T移动赋值运算符被称为等于擦除元素之后的向量中元素数量的次数。

So you see that C++11/14 implementation is more efficient in general since it perform move assignment instead of copy assignment, but the complexity remains the same. 因此,您可以看到C ++ 11/14实现通常更有效,因为它执行移动分配而不是复制分配,但复杂性保持不变。

std::deque 的std ::双端队列

The complexity of std::deque::erase() is linear both to the length of the range erased and to the minimum of two numbers: number of remaining elements before the start of the range, and number of remaining elements after the end of the range. std::deque::erase()的复杂性与std::deque::erase()范围的长度和两个数字的最小值呈线性关系:范围开始前剩余元素的数量,以及结束后剩余元素的数量范围。 So, erasing an element either from the beginning or from the end takes constant time. 因此,从开头或结束擦除元素需要恒定的时间。

C++2003 [lib.deque.modifiers] : C ++ 2003 [lib.deque.modifiers]

iterator erase(iterator position);
iterator erase(iterator first, iterator last);

Complexity: The number of calls to the destructor is the same as the number of elements erased, but the number of the calls to the assignment operator is at most equal to the minimum of the number of elements before the erased elements and the number of elements after the erased elements. 复杂性:对析构函数的调用次数与擦除的元素数相同,但对赋值运算符的调用次数最多等于擦除元素之前的元素数量和元素数量的最小值擦除后的元素。

C++14 draft N4140 [deque.modifiers]/5 : C ++ 14 draft N4140 [deque.modifiers]/5

Complexity: The number of calls to the destructor is the same as the number of elements erased, but the number of calls to the assignment operator is no more than the lesser of the number of elements before the erased elements and the number of elements after the erased elements. 复杂性:对析构函数的调用次数与擦除的元素数相同,但对赋值运算符的调用次数超过擦除元素之前的元素数量和之后的元素数量中的较小者。擦除元素。

So, it's the same in C++98 and C++11/14, again except that C++11 can choose between move assignment and copy assignment (here I see some inconsistency in the standard because the wording doesn't mention move assignment like for std::vector - might be a reason for another question). 所以,它在C ++ 98和C ++ 11/14中是相同的,除了C ++ 11可以在移动赋值和复制赋值之间进行选择(这里我看到标准中的一些不一致,因为措辞没有提到移动像std::vector这样的赋值 - 可能是另一个问题的原因)。

Note also the "at most" and "no more" in the wordings. 还要注意措辞中的“最多”和“不再”。 This allows for implementations to be more efficient than linear, though in practice they are linear ( DEMO ). 这允许实现比线性更有效,但在实践中它们是线性的( DEMO )。

Erasing an element in a vector is O(n) since once you remove the element you still need to shift all successive elements to fill the gap created. 删除向量中的元素是O(n),因为一旦删除元素,您仍需要移动所有连续元素以填充创建的间隙。 If a vector has n elements, then at the worst case you will need to shift n-1 elemets, hence the complexity is O(n). 如果向量具有n个元素,那么在最坏的情况下,您将需要移位n-1个元素,因此复杂度为O(n)。

Removing elements is indeed O(n) not because of what you have to do to find the element to remove but because of what you have to do to all of the ones after it. 删除元素确实是O(n)不是因为你需要做什么来找到要删除的元素,而是因为你必须对它之后的所有元素做什么。 Those elements need to be slid down to fill the empty slot. 需要向下滑动这些元素以填充空槽。

So on average, erase will take an element about halfway through the vector, so you'll have to shift about half the elements. 因此,平均而言,擦除将在向量的中间占据一个元素,因此您必须移动大约一半的元素。 Hence O(n) . 因此O(n) Best case, you erase the last element - no sliding necessary. 最好的情况是,你删除最后一个元素 - 不需要滑动。 Worst case, you erase the first element - have to then move every other element. 最坏的情况是,你擦除第一个元素 - 然后必须移动每个其他元素。

by using this way time complexity = range length + shifting length(n - range end) 通过使用这种方式时间复杂度=范围长度+移位长度(n - 范围结束)

    vector<int> it = (vector<int>::iterator) &vec[pos];
    vec.erase(it, it+length);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM