【发布时间】:2013-09-19 15:42:23
【问题描述】:
如果我们不断地在容器的前后添加,则需要选择双端队列而不是向量。但是抵消呢?
vector's 和 deque's operator[] 是否工作相同?如果不是,哪个更快?
【问题讨论】:
-
相关(但不重复):What really is a deque in STL?
如果我们不断地在容器的前后添加,则需要选择双端队列而不是向量。但是抵消呢?
vector's 和 deque's operator[] 是否工作相同?如果不是,哪个更快?
【问题讨论】:
std::vector<T> 是T 元素的平面数组。 std::deque<T> 是一个大小相等的 T 数组。在这两种情况下,索引访问的复杂性都是 O(1),但std::deque<T> 需要做更多的工作来确定要访问的元素,并且还有一个指示。就像,std::deque<T> 上的迭代器需要进行多次检查(尽管算法可以优化这一点,主要是通过识别分段结构使开销相当小。因此,如果您需要经常使用下标运算符,std::deque<T> 可能是一个糟糕的选择并且在前面插入/删除时在std::vector<T> 中移动元素的成本可能会被抵消。
简单解释一下,std::deque<T>在使用下标运算符的情况下大概需要做什么:可以考虑做这些操作:
T& deque<T>::operator[](size_t n) {
n += this->first_element;
size_t subarray = n / size_of_subarrays;
size_t index = n % size_of_subarrays;
return this->subarrays[subarray][index];
}
除法/模数运算符不太可能太昂贵,因为几乎可以肯定选择size_of_subarray 是 2 的幂,即它们基本上相当于位运算。
【讨论】:
std::deque<T> 比迭代 std::list<T> 更快,但这需要测量。天真地迭代双端队列将比迭代向量慢。理想的数据结构将是一个暴露其内部分段结构的双端队列,例如,通过使用分段迭代器,并在迭代双端队列的算法中考虑这种分段:它在迭代期间将具有几乎有效的访问,并且在插入时具有良好的行为前端和末端。我会用 deque 看看是不是太慢了。
对于双端队列
下标接近向量的效率
Bjarne Stroustrup《C++ 编程语言》17.2.3
这并不完全相同,因为访问元素需要一个额外的间接。在许多情况下,这又会由于缓存未命中而导致额外的内存命中。因此,随机访问的速度可能要慢几个数量级(实际上,大约是 1000 倍)。但是,这会为多次连续访问摊销,因此在实践中通常不会那么糟糕。
【讨论】:
std::deque 类似于std::vectors 的列表,所以如果你真的需要[] 运算符,std::vector 会更快地获取数据,但差异不大,所以你最好看看你多久前后推送数据以确定您是否需要std::vector 或std::deque。
还有一点,如果你使用 for 循环来获取容器的一些索引,你最好使用iterator,因为从std::vector 和std::deque 获取数据的速度差异不会很明显。
【讨论】:
vector,那么vector 和deque 之间的区别就更不明显了。