为什么不总是使用圆形数组deques而不是数组列表?

时间:2015-07-11 06:20:06

标签: arrays data-structures computer-science deque

几乎所有编程语言都有一些使用动态数组的列表实现,动态数组在达到一定容量时会自动扩展。例如,Java有ArrayList,C ++有std::vector

最近我学习了圆形阵列deques,它也是使用动态数组实现的。它们跟踪列表的起始索引,并使用模运算来访问元素。与数组列表一样,它们允许在末尾进行O(1)查找和O(1)插入,并且与O(N)成比例的空间。但是,它们也允许在开始时插入O(1)。

(虽然Java的ArrayDeque实现了这种数据结构,但它不允许查找元素.C ++的std::deque似乎使用了不同的实现。)

如果这些数组deques与数组列表具有相同或更好的性能特征,那么为什么不总是将它们用作列表的默认实现呢?

1 个答案:

答案 0 :(得分:1)

如果您不需要插入列表的头部,那么圆形双端队列会产生不必要的开销,例如:索引方法。在循环双端队列中,访问索引i需要在访问底层数组之前将i添加到head元素的索引并循环(例如,使用模运算符或按位运算符),而使用vanilla向量时,在访问之前不需要对i进行操作底层数组。

为了证明这种开销,典型的deque实现可能如下所示:

template <typename T>
class Deque {
  private:
    T* array; // The underlying array, holding elements of the deque.
    int size; // The number of elements held by the deque.
    int capacity; // The size of array ** must be a power of two **.
    int head; // The index of the head element within array.

  public:
    T& operator[](int index) {
        // Notice the calculation required before accessing array.
        return array[(head + index) & (capacity - 1)]
    }
};

此外,如果您需要访问从索引0开始元素连续的基础数组,则无法传递deque。

请参阅问题Why would I prefer using vector to deque,这与您的问题非常相似。