0% found this document useful (0 votes)
10 views

2.3 ArrayQueue - An Array-Based Queue

This document describes the ArrayQueue data structure, which implements a FIFO queue using a circular array. It supports adding and removing elements in O(1) time per operation by using modular arithmetic to treat the array as circular. Resizing the array is also supported in O(n) time to ensure the number of elements doesn't exceed the array size.

Uploaded by

Sergey Shamirian
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

2.3 ArrayQueue - An Array-Based Queue

This document describes the ArrayQueue data structure, which implements a FIFO queue using a circular array. It supports adding and removing elements in O(1) time per operation by using modular arithmetic to treat the array as circular. Resizing the array is also supported in O(n) time to ensure the number of elements doesn't exceed the array size.

Uploaded by

Sergey Shamirian
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Next: 2.4 ArrayDeque: Fast Deque Up: 2. Array-Based Lists Previous: 2.

2 FastArrayStack: An
Optimized Contents Index

Subsections

2.3.1 Summary

2.3 ArrayQueue: An Array-Based Queue


In this section, we present the ArrayQueue data structure, which implements a FIFO (first-in-first-out)
queue; elements are removed (using the operation) from the queue in the same order they

are added (using the operation).

Notice that an ArrayStack is a poor choice for an implementation of a FIFO queue. It is not a good
choice because we must choose one end of the list upon which to add elements and then remove
elements from the other end. One of the two operations must work on the head of the list, which
involves calling or with a value of . This gives a running time

proportional to .

To obtain an efficient array-based implementation of a queue, we first notice that the problem would
be easy if we had an infinite array . We could maintain one index that keeps track of the next
element to remove and an integer that counts the number of elements in the queue. The queue
elements would always be stored in

Initially, both and would be set to 0. To add an element, we would place it in and

increment . To remove an element, we would remove it from , increment , and decrement .

Of course, the problem with this solution is that it requires an infinite array. An ArrayQueue simulates
this by using a finite array and modular arithmetic. This is the kind of arithmetic used when we are

talking about the time of day. For example 10:00 plus five hours gives 3:00. Formally, we say that
:
We read the latter part of this equation as ``15 is congruent to 3 modulo 12.'' We can also treat

as a binary operator, so that

More generally, for an integer and positive integer , is the unique integer
such that for some integer . Less formally, the value is the

remainder we get when we divide by . In many programming languages, including Java, the

operator is represented using the symbol.2.2

Modular arithmetic is useful for simulating an infinite array, since always gives a

value in the range . Using modular arithmetic we can store the queue elements at
array locations

This treats the array like a circular array in which array indices larger than ``wrap
around'' to the beginning of the array.

The only remaining thing to worry about is taking care that the number of elements in the
ArrayQueue does not exceed the size of .

T[] a;
int j;
int n;

A sequence of and operations on an ArrayQueue is illustrated in Figure 2.2. To

implement , we first check if is full and, if necessary, call to increase the size of

. Next, we store in and increment .


:
Figure 2.2: A sequence of and operations on an
ArrayQueue. Arrows denote elements being copied. Operations that
result in a call to are marked with an asterisk.

boolean add(T x) {
if (n + 1 > a.length) resize();
a[(j+n) % a.length] = x;
n++;
return true;
}

To implement , we first store so that we can return it later. Next, we decrement and

increment (modulo ) by setting . Finally, we return the stored

value of . If necessary, we may call to decrease the size of .

T remove() {
if (n == 0) throw new NoSuchElementException();
T x = a[j];
j = (j + 1) % a.length;
n--;
if (a.length >= 3*n) resize();
:
return x;
}

Finally, the operation is very similar to the operation of ArrayStack. It allocates

a new array, , of size and copies

onto

and sets .

void resize() {
T[] b = newArray(Math.max(1,n*2));
for (int k = 0; k < n; k++)
b[k] = a[(j+k) % a.length];
a = b;
j = 0;
}

2.3.1 Summary

The following theorem summarizes the performance of the ArrayQueue data structure:

Theorem 2..2 An ArrayQueue implements the (FIFO) Queue interface. Ignoring the cost of calls to
, an ArrayQueue supports the operations and in time per

operation. Furthermore, beginning with an empty ArrayQueue, any sequence of and

operations results in a total of time spent during all calls to .

Footnotes
:
... symbol.2.2
This is sometimes referred to as the brain-dead mod operator, since it does not correctly
implement the mathematical mod operator when the first argument is negative.

Next: 2.4 ArrayDeque: Fast Deque Up: 2. Array-Based Lists Previous: 2.2 FastArrayStack: An
Optimized Contents Index
opendatastructures.org
:

You might also like