ArrayDeque: Fast Deque Operations Using an Array
Explore the ArrayDeque data structure to understand how it supports efficient double-ended queue operations using a circular array. Learn how add and remove operations minimize shifting elements, optimizing runtime performance. This lesson enables you to implement and manipulate ArrayDeques for quick insertions and deletions at either end.
We'll cover the following...
The ArrayQueue is a data structure for representing a sequence that allows us to efficiently add to one end of the sequence and remove from the other end. The ArrayDeque data structure allows for efficient addition and removal at both ends. This structure implements the List interface by using the same circular array technique used to represent an ArrayQueue.
The ArrayDeque operations
The get(i) and set(i, x) operations on an ArrayDeque are straightforward. They get or set the array element a[(j + i) mod a.length].
The implementation of add(i, x) is a little more interesting. As usual, we first check if a is full and, if necessary, call _resize() to resize . Remember that we want this operation to be fast when is small (close to ) or when is large (close to ). Therefore, we check if . If so, we shift the elements left by one position. Otherwise , we shift the elements right by one position.
Visual demonstration
See the below illustration of add(i, x) and remove(x) operations on an ArrayDeque. Arrows denote elements being copied.
The implementation of the add() method is:
By doing the shifting in this way, we guarantee that add(i, x) never has to shift more than min{i, n − i} elements. Thus, the running time of the add(i, x) operation (ignoring the cost of a resize() operation) is .
The implementation of the remove(i) operation is similar. It either shifts elements right by one position or shifts the elements left by one position depending on whether . Again, this means that remove(i) never spends more than time to shift elements.
Summary
The following theorem summarizes the performance of the ArrayDeque data structure:
Theorem: An ArrayDeque implements the List interface. Ignoring the cost of calls to resize(), an ArrayDeque supports the operations
-
get(i)andset(i, x)in time per operation; and -
add(i, x)andremove(i)in time per operation.
Furthermore, beginning with an empty ArrayDeque, performing any sequence of add(i, x) and remove(i) operations results in a total of time spent during all calls to _resize().
Explanation
Let’s start our explanation from the start of main() in the main.py file.
- Line 60: It creates an instance of the
ArrayDequeclass, which is a double-ended queue (deque) that can store objects of typeInteger. - Line 62: It shows the empty
deque. - Lines 63–65: It adds values to the
deque. - Line 66: It prints the
deque. - Line 68–69: It removes an element at index
1and then prints thedequeafter removal. - Line 72–73: It clears the
dequeand prints thedequeafter theclear()method.