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

  1. 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.
    1. (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. (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).
    3. (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).
    4. (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.)
  2. 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.
    1. (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).
    2. (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?
  3. 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.
    1. (2 points) Of the three sorts described in class, is any one of them better for this application? Explain in a few sentences why.
    2. (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. (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.

  1. (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.
  2. (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. (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).
  4. (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. ;-))