 : An Array-Based Queue
: An Array-Based Queue
In this section, we present the 
 data structure, which
implements a FIFO (first-in-first-out) queue; elements are removed (using
the
 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) from the queue in the same order they are added
(using the 
 operation).
 operation).
Notice that an 
 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
 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
 or 
 with a value of
 with a value of 
 .
This gives a running time proportional to
.
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
.  We could maintain one index 
 that keeps track of the
next element to remove and an integer
 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
 that counts the number of
elements in the queue.  The queue elements would always be stored in
![$\displaystyle \ensuremath{\mathtt{a[j]}},\ensuremath{\mathtt{a[j+1]}},\ldots,\ensuremath{\mathtt{a[j+n-1]}} \enspace . $](img806.png) 
 and
 and 
 would be 
set to 0.  To add an element, we would place it in
 would be 
set to 0.  To add an element, we would place it in 
![$ \mathtt{a[j+n]}$](img809.png) and increment
 and increment 
 .
To remove an element, we would remove it from
.
To remove an element, we would remove it from 
![$ \mathtt{a[j]}$](img811.png) , increment
, increment 
 , and
decrement
, and
decrement 
 .
.
Of course, the problem with this solution is that it requires an infinite
array.  An 
 simulates this by using a finite array
 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
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
 
 as a binary operator, so that
 as a binary operator, so that
 
More generally, for an integer  and positive integer
 and positive integer  ,
,  is the unique integer
is the unique integer 
 such that
 such that 
 for
some integer
 for
some integer  .  Less formally, the value
.  Less formally, the value  is the remainder we get
when we divide
 is the remainder we get
when we divide  by
 by  .
In many programming languages, including
C++, the
.
In many programming languages, including
C++, the  operator is represented
using the
 operator is represented
using the 
 symbol.2.2
 symbol.2.2
Modular arithmetic is useful for simulating an infinite array,
since 
 always gives a value in the range
 always gives a value in the range
 .  Using modular arithmetic we can store the
queue elements at array locations
.  Using modular arithmetic we can store the
queue elements at array locations
![$\displaystyle \ensuremath{\mathtt{a[j\%a.length]}},\ensuremath{\mathtt{a[(j+1)\%a.length]}},\ldots,\ensuremath{\mathtt{a[(j+n-1)\%a.length]}}
\enspace. $](img832.png) 
 like a circular array
in which array indices
larger than
 like a circular array
in which array indices
larger than 
 ``wrap around'' to the beginning of
the array.
 ``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 
 does not exceed the size of
 does not exceed the size of 
 .
.
array<T> a; int j; int n;
A sequence of 
 and
 and 
 operations on an
 operations on an 
 is
illustrated in Figure 2.2.  To implement
 is
illustrated in Figure 2.2.  To implement 
 , we first
check if
, we first
check if 
 is full and, if necessary, call
 is full and, if necessary, call 
 to increase
the size of
 to increase
the size of 
 .  Next, we store
.  Next, we store 
 in
 in
![$ \mathtt{a[(j+n)\%a.length]}$](img845.png) and increment
 and increment 
 .
.
| ![\includegraphics[scale=0.90909]{figs/arrayqueue}](img847.png)  | 
  bool add(T x) {
     if (n + 1 > a.length) resize();
     a[(j+n) % a.length] = x;
     n++;
     return true;
   }
To implement 
 , we first store
, we first store 
![$ \mathtt{a[j]}$](img853.png) so that we can return
it later.  Next, we decrement
 so that we can return
it later.  Next, we decrement 
 and increment
 and increment 
 (modulo
 (modulo 
 )
by setting
)
by setting 
 .  Finally, we return the stored
value of
.  Finally, we return the stored
value of 
![$ \mathtt{a[j]}$](img858.png) . If necessary, we may call
. If necessary, we may call 
 to decrease the
size of
 to decrease the
size of 
 .
.
  T remove() {
    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 is very similar to the 
 operation of
operation of 
 .  It allocates a new array,
.  It allocates a new array, 
 , of size
, of size 
 and copies
and copies
![$\displaystyle \ensuremath{\mathtt{a[j]}},\ensuremath{\mathtt{a[(j+1)\%a.length]}},\ldots,\ensuremath{\mathtt{a[(j+n-1)\%a.length]}}
$](img866.png) 
![$\displaystyle \ensuremath{\mathtt{b[0]}},\ensuremath{\mathtt{b[1]}},\ldots,\ensuremath{\mathtt{b[n-1]}}
$](img867.png) 
 .
.
  void resize() {
    array<T> b(max(1, 2*n));
    for (int k = 0; k < n; k++)
      b[k] = a[(j+k)%a.length];
    a = b;
      j = 0;
  }
The following theorem summarizes the performance of the 
 data structure:
data structure:
 implements the (FIFO)
 implements the (FIFO) 
 interface.  Ignoring the cost of
calls to
 interface.  Ignoring the cost of
calls to 
 , an
, an 
 supports the operations
 supports the operations
 and
 and 
 in
 in  time per operation.
Furthermore, beginning with an empty
 time per operation.
Furthermore, beginning with an empty 
 , any sequence of
, any sequence of  
 and
 and 
 operations results in a total of
 operations results in a total of  time spent during all calls to
time spent during all calls to 
 .
.