CS 261 University of Puget Sound Spring, 2020
 
Computer Science II
Abstract Data Types and their Implementations, Some Basic Algorithms,
Object-oriented Problem Solving, and Efficiency
 

Warning: This course is under development. Although the basic structure of this course is largely established, nothing on this Web site should be considered official or even possibly correct.
DO NOT MAKE PLANS BASED ON THE CONTENTS OF THIS SITE UNTIL JANUARY, 2020.

Laboratory Exercise on Queues with Arrays

Goals

This laboratory exercise introduces the concept of the queue abstract data type and provides experience implementing this ADT.

After introductory material on queues as abstract data types, work on queue implementations proceeds in two parts:

  1. Implementation of queues with arrays (this lab)
  2. Implementation of queues with linked lists (the next scheduled lab)

Queues as ADTs

Today's reading on queues describes a queue as an ADT that can store data and that has the following operations:

A Potential Queue Interface in Java

Typical methods for a queue follow:

   /* a constructor for an empty queue
   */
   
  /* return whether the queue is empty
     pre:  queue is an initialized queue
     post: returns true if queue is empty;
           false otherwise
   */
  public boolean isEmpty ()
  
  /* return whether the queue is full
     pre:  queue is an initialized queue
     post: returns true if an additional item
              cannot be added to the queue;
           false otherwise
   */
  public boolean isFull ()

  /* insert given item into back of the queue
     pre:  the specified queue is initialized
     returns:  null if queue is full
               otherwise, reference to item added
   */
  E enqueue (E item)

  /* removes front item from queue referenced by parameter
     pre:  the specified queue is initialized
     returns:  null if queue is empty
               otherwise, reference to the item removed
   */
  E dequeue ()


Implementing Queues with Arrays

Be sure you have read the reading on queues, particularly the reading on the implementation of queues by arrays, before continuing.

In this part of the lab, we will focus on arrays of generic type E. The relevant fields are:

  public class Queue <E> {
    protected first;
    protected last;
    protected count;
    E queueArray [] ;
    ...
    

A constructor would initialize the queueArray to an array of a specified size. (Pragmatically, the size might be a constructor parameter.)


Work Started in Class

Additional implementation notes may be found in today's reading on Queues.

  1. Write two implementations of a queue of strings by implementing these operations.

    1. In one implementation, use the following interpretations for the first and last fields (as discussed in the right column).
      • last designates the location of the most recent item inserted into the queue. (lastA in the diagram.)
      • first designations the location where the next item will be removed from the queue.
    2. In the second implementation, use the following interpretations for the first and last fields (as discussed in the right column).
      • last designates the location where the next item will be inserted into the queue. (lastB in the diagram.)
      • first designations the location where the previous item was removed from the queue.
  2. Use the queue operations within a main procedure to provide thorough testing of each operation.

Homework

  1. Add to the queue ADT an additional procedure print that displays each of the elements of the queue on a separate line (without actually removing any of them from the queue).

  2. An alternative approach for the dequeue procedure would add a parameter item to the list of parameters and change the return type to an int type. The idea is that the string would be returned as a parameter char * item and the procedure would return the length of the string item or -1 if the queue was empty. The relevant procedure signature might be:

      int dequeue (stringQueue * queue, char ** item)
    

    and this procedure would be called within the context:

      char * frontItem;
      int returnValue;
      stringQueue myQueue;
      ...
      returnValue = dequeue (&myQueue, &frontItem)
    
    1. The parameter item has type char **, and the call to queue includes &frontItem. Explain why ** and & are needed here.
    2. Write this alternative version of the dequeue operation.

Two alternative interpretations of last, and two for first

Typically, the last records where new items will be added to a queue. However, at least two interpretations are possible:

Alternative interpretations for the last field

In the diagram, note lastB = lastA + 1

In an array implementation of a queue, either interpretation can work without trouble, but the details are different:

Also, assuming the very first item will be placed in array element 0, the initializations of the index fields must be different.

As noted, either approach can work without trouble, but mixing the two interpretations will likely yield errors. Choosing an interpretation may be called specifying an invariant of the queue code. Throughout all queue operations, the interpretation of last (i.e., using lastA or lastB) never varies. Likely the code will use the simple field name last, but the programmer will need to have decided which approach is being used.

A similar two choices are possible for first



created 16 August 2011 by Dilan Ustek (questions by Henry Walker)
revised 16 August 2011 by Dilan Ustek
reformatted and edited 4 February 20134 by Henry M. Walker
readings added 19 September 2014 by Henry M. Walker
revised to updated format 14-16 April 2016 by Henry Walker
reorganized into two labs 1 February 2020 by Henry Walker
Valid HTML 4.01! Valid CSS!