CS3134 Homework #2
Due on October 9, 2003 at 11:00am
There are two parts to this homework: a written component worth
15 points, and a programming assignment worth 10 points. See
the homework submission
instructions on how to hand it in and for important notes on
programming style and structure.
Note: parts in red are
revisions/clarifications. See the webboard for a more detailed
explanation.
Written questions
- All three sorts we've covered so far (bubble, insertion, and
selection) are rather inefficient in sorting large arrays.
Let's assume I have a large array of elements ordered
backwards. Sorting such an array takes O(n2) time for all
three, which for large n (say, more than 1000) is rather slow.
There are a number of alternatives we can develop that should
run much faster.
- (2 points) As we described in class, a stack can
be used to reverse items. Explain in a few sentences what
sequence of stack operations would do just this. State,
using big-Oh notation, the worst-case running time for such
an algorithm, and explain in a few sentences why. (Hint:
explain how the combination of many low-level stack
operations "adds up" to such a high-level worst-case
time.)
- (2 points) Describe an alternative algorithm,
using approximately 5-10 sentences, that we can use if we
wanted to only use the one array to store information,
instead of having to create an additional data structure
(like a stack) to manipulate the data. Such an algorithm
might be called in-place -- that is, the data
elements are manipulated mostly within the array itself (a
few individual external variables notwithstanding). Try to
be as precise as possible (i.e., if necessary, enumerate
each step one at a time).
- (2 points) Approximate the worst-case running time of
(b), using a similar analysis to (a) (that is, decomposing
the high-level operation into a series of lower-level steps
and combining their respective running times).
- (1 point) Of these two, which is more efficient, and
why? Use 2-3 sentences to explain. An informal analysis of
space and/or time usage should be sufficient. (Note: this
does not imply that the approximate worst-case
running times are necessarily different. They may very well
be equal, but one of the two will still have their
advantages.)
- In class, we spent most of our time describing stable
unordered lists, that is, lists which would try to maintain the
inputted order of the elements. Let's relax this requirement
and think of an unordered array-backed list that is
unstable, i.e., operations on some elements in the list
may cause others' ordering to change.
- (2 points) Describe, in a few sentences, a remove
algorithm that takes only O(1) time, instead of the O(n)
remove algorithm that was described both in class and in the
book. Note that I'm referring to the
process of removing an element itself; you may assume you
know which index is to be removed (i.e., we're not concerned
with the search aspects).
- (1 point) If we relax the definition of stability on an
ordered list, can we improve the running time of any
of the basic list operations (e.g., insert, remove, search)?
Why or why not?
- Let's imagine a "lazily-sorted" list, which would usually be
an ordered list, but we relax the restriction that insert must
always insert a new element in the right position. Instead,
insert puts elements at the end, and then we occasionally resort
the list. Criterion for reshuffling the list might include the
insertion of 10 elements in unsorted order at the end or a
remove/search attempt that uses a binary search.
- (2 points) Of the three sorts
described in class, is any one of them better for this
application? Explain in a few sentences why.
- (0 points; this subproblem
cancelled)
Let's imagine I have a
lazily-sorted list with 90 sorted elements and 9 unsorted
elements sitting at the very end. I add one more unsorted
element, which triggers an auto-resort. Using the sort
algorithm you described in (a) -- or any sort algorithm if
you feel they're equivalent -- calculate the number of
comparisons (i.e., an absolute number, not in terms of
n) and the number of assignments that need to be
done, and show your work. (Note that a "swap" is typically
three assignments.)
- (3 points) Make a qualitative comparison, based on the sort
method you chose in (a) (or any of the three if you didn't
choose one in particular) of the effort needed to sort a
completely-unsorted list of 100 items as opposed to a
lazily-sorted list with 90 sorted elements and 10 unsorted
items. Explain in a few sentences which is faster, and why
this is the case.
Programming problem
The manager of IdiotBank is still in a bind: you created an
account management system for him, but he needs a counter
management system, one that deals with lines of people
efficiently. You decide to use a Queue as a fundamental data
structure to help with their operations, but first need to add
some features to it to make it useful.
In other words, the goal of this problem is to add some features
to the Queue class given in the book (page 138; download here). There are four subparts
to this assignment. Note that you do
not have to use code or data structures from the first
assignment; working with a queue of longs, as the
book's code does, is sufficient.
-
(2 points) Book programming project 4.1. That is, write a
method in Queue called dump that prints out
the contents of the queue to the screen when called. The
method takes no parameters and returns no values. As the book
warns, you must start from the "first" element to the "last"
-- you can't just iterate from the 0th to
the last element of the array.
-
(4 points) Another way of building a priority queue is to
prioritize an existing queue. Implement a method
called prioritize that takes no parameters and
returns no values in Queue. To prioritize, simply
implement a bubble sort that arranges the queue such
that the smallest values are "first" and the largest values
are "last". (Note that future insertions may destroy the
priority ordering of the prioritized queue, which is fine; we
can call prioritize again.)
-
(3 points) Make the Queue auto-expandable. By
default, the constructor specifies an initial length; however,
if the queue fills up, there's no error and data gets
overwritten. Instead, check on insert to make sure the
queArray isn't full, and if it is full,
create a new array twice the length, copy the existing queue
to the new array, and set the queArray reference to
the new array. Be careful that you maintain the order of the
queue, although you can rearrange the location of the front
and rear if you want to. To demonstrate that your
Queue is resizing correctly, write a
capacity method that takes no parameters but returns
an int -- the length of the array itself (as opposed to
nItems).
-
(1 point) Modify the QueueApp class to test your code
appropriately. That is, make sure to insert some elements,
remove others, and do a variety of dump,
capacity and prioritize calls that
demonstrate your Queue's functionality when you run
the code. You'll submit this modified QueueApp, but
also note that the TAs will also have their own
QueueApp that will run their own sequences of
inserts, removes, prioritizes and dumps, so make sure you name
the methods exactly as described above. (I
could have made you do a user interface instead, but repeating
that from the previous assignment is tedious. ;-))