Put It Together
For this assignment, you are to create two template classes,
rpt_queue and its inverse expand_queue.
The rpt_queue class behaves somewhat like an ordinary
queue, except that it groups matching items together. It allows
you to push single items like a normal queue, but when you pop you
get an item and a repeat count. When you push the same item three
times in a row, pop gives you the item once with a repeat count of three.
The expand_queue is the inverse. Its push takes an item and
a count, and its pop will deliver the item the indicated number of times
The Repeating Queue
The
rpt_queue template class takes a single
typename
template parameter giving the type of object contained in the queue.
An object
q of type
rpt_queue<T> has the following interface:
q.push(const T &item)
Push a copy of item onto the queue.
q.pop(T &item)
Pop an item from the stack. If no item is available, the method returns
zero and does nothing else. If some item is available, pop stores
a copy in the parameter item, and returns a positive
count of consecutive
items of this value. Note that there is no such thing as an empty
group: if there is something in the list, the method returns a group with
more than one item; if the queue is empty there is no group to produce and
the method returns 0.
q.empty() const
Returns true if q is empty, false otherwise.
For instance,
rpt_queue<int> q;
q.push(10);
q.push(10);
q.push(3);
q.push(18);
q.push(18);
q.push(18);
q.push(10);
creates a queue which can be successfully popped four times. The first pop
returns 2 and stores 10 into the parameter item; the second pop
returns 1 and stores 3 into the parameter item. The third gives 3 and 18,
and the fourth 1 and 10.
The fifth (and any more absent another push) gives 0 and does not
store anything in its parameter.
The Expanding Queue
The
expand_queue template class takes a single
typename
template parameter giving the type of object contained in the queue.
An object
q of type
expand_queue<T> has the following interface:
q.push(int count, const T &item)
For positive count,
this pushes count repetitions of value item.
For zero or negative count, nothing is pushed; a push
with a zero count does exactly nothing.
q.pop(T &item)
Pop an item from the stack. If no item is available, the method returns
false and does nothing else. If some item is available, pop stores
a copy in the parameter item removing it from
q, and returns true.
Item will be returned for
count successive pop calls, where count is the parameter
used when item was pushed.
q.empty() const
Returns true if q is empty, false otherwise.
For instance,
expand_queue<int> q;
q.push(3,10);
q.push(2,18);
q.push(0,5);
q.push(1,1);
creates a queue that can be successfully popped 6 times, giving
10, 10, 10, 18, 18, and 1. The seventh and successive pops return false
and store nothing in parameter
item.
Arrangement
Both of the classes are templates, so they should be placed entirely in
a .h file; don't create a .cpp file. Put both in the
same .h file, which you may name as you like. The examples given
here assume the name rtpq.h, but this is not a requirement.
Do use the #ifndef/#define/#endif pattern
as described earlier in your .h file to avoid multiple declaration
errors at compile time.
Notes
You should hold your data in some private list or vector.
There are basically two approaches:
- Your list or vector can simply hold one copy of each item in the
queue
- Your list or vector can hold a list of pairs containing an item
and its count.
For option 1, you will simply have a private list or vector of T to
hold your data. For 2, you can either create a small
(template) class holding
an integer and a T, or by using
std::pair. (This is the same thing std::map contains, with
fields first and second.)
Option 1 may be simpler to understand, but it take more space and
each class will require a loop, in rpt_queue<T>::pop and
expand_queue<T>::push. Option 2 allows the classes to be
written without loops.
Submission
When your program works, is well-commented, and nicely indented,
submit over the web
here.