Homework 7: The Queue ADT
Circular Array Implementation
Overview
In this homework, you will implement the Queue ADT using a circular array based implementation. The circular attay implementation provides efficient implementation of enqueue and dequeue operations by allowing both ends of the list to move through the indices of the array and "wrap around" the end of the array back to the beginning of the array. This gives the circular part of the implementation. Constructors should dynamically allocate the array storage.
This assignment will use template Queue classes so that we can define queues of integers or queues of doubles or queues of characters easily. We will keep the application simple, limited to a general purpose driver program.
Attributes/Structure
- The primary data item/attributes of a Queue object is a finite length homogeneous collection of data items arranged in sequential fashion:
- It is homogenious -- the elements in the collection are all of the same type.
- It has a finite length (the number of elements).
- The elements are arranged sequentially:
- There is a first element and a last element
- Every element except the last has a unique successor
- Every element except the first has a unique predecessor
- The first element of the sequence is referred to as the beginning (aka front, head) of the queue and is the element removed during a dequeue operation. The last element of the sequeunce is the end (aka back, tail) of the queue and is the point where all insertions occur during enqueue operations.
Operations
Note in the following description of the operations, I will use DT (instead of Item) to abstractly represent the data type of the elements of the queue. In the template impementation of the Queue class, this will be the passed template type.
Constructor/Destructor
Queue ( )
Preconditions: None.
Postconditions: Creates an empty queue capable of holding MAX_SIZE data items of type DT. Beginning and end of the queue indicate no element.Queue ( int capacity )
Preconditions: 0 <= capacity < MAX_SIZE
Postconditions: Creates an empty stack capable of holding capacity data items of type DT. Beginning and end of the queue indicate no element.Queue ( const Queue & orig )
Preconditions: None.
Postconditions: Creates a new queue that is a copy of the given orig queue. Note that the new queue shares no storage with the original queue.~Queue ( )
Preconditions: None.
Postconditions: Destroys the queue, cleaning up all resources associated with the object.Mutator(s)
void enqueue ( const DT & item )
Preconditions: Queue is not full (i.e. the number of items currently in the queue is less than its capacity).
Postconditions: The item has been inserted at the end of the sequence, and the end is positioned at the newly inserted item.DT dequeue ( )
Preconditions: The queue is not empty.
Postconditions: The item at the beginning of the queue is removed and returned. The beginning becomes the item's successor in the sequence, or represents EMPTY if the queue is now empty.void clear ( )
Preconditions: None.
Postconditions: The queue is empty and all resources have been returned to the system.Queue & operator= ( const Queue & rhs )
Preconditions: None.
Postconditions: Previous queue resources have been returned to the system and the queue has become a copy of the given Queue rhs. The current queue is returned.Observers (Predicates and Accessor(s))
bool isEmpty ( ) const
Preconditions: None.
Postconditions: Return value is true if the queue contains no items, and false otherwise.bool isFull ( ) const
Preconditions: None.
Postconditions: Return value is true if the queue contains its capacity of items, and false otherwise.DT first ( ) const
Preconditions: The queue is not empty.
Postconditions: The item at the beginning of the queue is returned. The queue does not change.Print/String
void display ( ostream & stream ) const
Preconditions: DT type supports stream insertion to an output stream.
Postconditions: Outputs the contents of the queue to the given stream. Form of the output must be strictly adhered to. The output uses '(' and '$)' to denote the extent of the queue. The stack is output with the beginning at the left hand end. The output uses space separation between elements of the queue as well as between the beginning '(' and the first element, and the ending '$)' and the last element. The stack display should terminate with a newline.Examples:
- Empty queue -- ( $)
- One element queue -- ( a $)
- Two element queue with a "in front of" b -- ( a b $)
- Three element queue with a at head of queue and c at tail -- ( a b c $)
Assignment
Be sure and use the C++ Programming Style Guide and follow the conventions described there. Up to 15% of the grade for this homework will be based on following these conventions and practicing good documentation.
Your task is to implement the Queue ADT using a circular array implementation. You must use a template class definition so that we can easily define different types of queues in the same program. For your driver, define your queues to be of type Queue<int> (i.e. an queue of base type int). You are also required to implement a non-member function that overloads the stream insertion operator for Queue objects. Please be sure that the stream insertion follows the print specification of the display operation.
You must create a test plan to thoroughly test all of your Queue operations, and demonstrate through use of a driver program that your operations perform correctly across the different tests of your test plan. Your driver should include the ability to use comments that are output when encountered with the '#' command. These should be used to explicity give the expected result of each test in your test plan.
The driver must allow the notion of two Queue objects, the "current" queue and the "alternate" queue. Single Queue object operations pertain to the "current" queue. For the copy constructor and the assignment overload, the "current" queue is the one that gets updated (is logically the lhs), and the "alternate" queue is the one that is copied from (is logically the rhs). There is also a command to switch the roles of the two queues, making the current the alternate and the alternate the current. Each command must also output the command and its argument, if any.
Files to turn in: Queue.h, Queue.cpp, QueueInst.cpp (see below), and QueueTest.cpp, along with your test file(s) implementing your test plan.
Test Queue Driver Commands Command Action CcCreate a new Queue object (using the new C++ operator), making it the current Queue; the command is immediately followed by an integer (c) which defines the capacity of the stack. For a queue with 0 specified capacity, create a "default" (MAX_SIZE) capacitly queue. DDestroy the current Queue object +xThe '+' command performs an enqueue operation on the current queue. The value to insert (x) immediately follows the '+' and is of type consistent with the type of the queue. -Perform a dequeue operation, displaying to cout the item dequeued from the queue. On an empty queue, the dequeue() precondition will be violated. @Display to cout the data item at the head of the queue. On an empty queue, the first() precondition will be violated. *Display the entire queue as specified above. EReport whether the queue is empty, printing TRUE or FALSE. FReport whether the queue is full, printing TRUE or FALSE. =Demonstrate assignment overload, assigning the alternate queue to the current queue. &Demonstrate copy constructor, creating a new current queue from the alternate queue. ~Switch the current queue with the alternate queue. #Ignore all following characters up to the following newline, outputing these characters as its argument. XDelete all elements in the queue. HPrint a help message with the supported commands and a brief description of their actions. QQuit the test program.
Helpful Files
File Description/Use intQueueTest.o This is the object file for a test program utilizing a non-template integer Queue. If your Queue class conforms to the (non-template) public interface given above, then you should be able to test your class with this driver. To create an executable for the above scenario, you would issue the following command:
g++ -o intQueueTest Queue.cpp intQueueTest.o
which compiles your Queue.cpp file and combines it with the intQueueTest.o object file into an executable named intQueueTest.
QueueInst.cpp This is a .cpp source file which explicitly instantiates templates for Queue<int>, Queue<char>, and Queue<double>. It performs a #include of "Queue.cpp" to access the template definitions of the template Queue class functions. Your implemenation file must be named "Queue.cpp" for this to work properly.
You should compile this file _instead of_ your Queue.cpp file, and use the result combined with your driver.
To compile just the template class definitions and generate instantiated versions for <int>, <char>, and <double>:
g++ -c QueueInst.cpp
To compile the driver and combine it with the Queue template instances, assuming the driver is named QueueTest.cpp:
g++ -o QueueTest QueueInst.o QueueTest.cpp