CS3134 Homework #3
Due on October 28, 2003 at 11:00am

There are two parts to this homework: a written component worth 10 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.

Written questions

  1. Doubly-linked, doubly-ended lists are fairly versatile data structures, but there's one major problem with them: scanning through them is still a tedious process -- for example, if you want to get to the middle of a linked list, it takes N/2 steps, even if you know what the value of N is. Compare this to an array, where going to the middle always takes one step. Let's see if we can come up with a better way.

    Imagine a doubly-linked list not only with "next" and "back" pointers, but with a "nextnext" pointer that points to the element after the next element. This enables us to skip through the list a bit quicker if we're scanning for a particular position, or if we have an ordered list and know approximately where our contents are.
    1. (2 points) Assuming we have a list with such a "nextnext" pointer, how much time (absolute, not big-Oh) do we save for accessing the 50th element in a 100-element list over a traditional doubly-linked list?
    2. (1 point) Does the time saved above realize into a change in the big-Oh complexity for this access process as compared to a traditional doubly-linked list? Why or why not?
    3. (2 points) If we want to insert a new item in the middle of this list, what references do we have to modify? How about delete? You can just list each of the references, the new value for each, and a brief explanation, or you can give psuedocode for each and explain why the psuedocode works. Also, list the boundary conditions and explain briefly how we'd address them (you don't need to write out the references or psuedocode for this).
    4. (3 points) Write out a jumpTo method that would belong in the new list class that takes one parameter: the index of the element we're looking for, and returns the Link element corresponding to that index (e.g., 5 would return the 6th item). Make sure you try and make this jumpTo as efficient as you can given this variation on the doubly-linked list. Express how many steps it would take (absolute, not big-Oh) for this search to run if we look for an index i in a list of n items. (Your code doesn't have to compile, but the syntax should be reasonably close to Java).
    (Trivia: this is the basis for a special data structure called a skip list, which is a cross between a tree and a linked list. It's a pretty cool data structure; do a Google search if you're curious about it.)
  2. (2 points) The book lists the code for the merge part of mergesort on page 281. It's iterative, as it's a bit quicker that way, but the code is convoluted. Write out the psuedocode to do merge recursively. Be as precise as you can: in particular, make sure specify the parameters to the method call, and illustrate the stopping case(s) and the recursive case(s). What's the complexity of the recursive merge?

Programming problem

In this exercise, we're going to add some functionality to the DoublyLinkedList class that was provided in the book (page 226; you can download a copy here). There are three subparts to this assignment. For each, make sure you modify the tester program to demonstrate the new functionality.

  1. (3 points) Implement a method that splits the doubly-linked list into two separate lists. To do this, build a method called split that takes a long as a parameter and returns a new object of type DoublyLinkedList. The method should search for the first instance of the supplied long, and split the list (or, to be more precise, reassign references) such that the found element should be the first element of the new DoublyLinkedList, and the element before it should be the last element of the old DoublyLinkedList. If that element doesn't exist, the method should return null. Make sure to take boundary conditions into account. Your algorithm should do the search in O(N) time and the actual splitting in O(1) time (e.g., you should not be actually copying the data itself around).
  2. (5 points) Implement a recursive insertion sort for this doubly linked list. To do this, create a method in the DoublyLinkedList class called recInsertionSort that takes no parameters. This method just needs to, in turn, call to another (private) method called recInsertionSort that takes two parameters: a reference to the first Link to be sorted recursively, and a reference to the last Link to be sorted recursively. Neither method returns any values. (Note that having two methods with the same name is legitimate Java syntax; it differentiates them by the parameter names. This is an OO concept known as overloading.)

    The strategy is as follows: a list of n elements can be insertion-sorted by first recursively sorting 0...n-1, and then inserting n in the correct spot amongst the (now sorted) n-1 elements. The stopping case is one Link, which of course is inherently sorted by definition.
  3. (2 points) Implement a recursive count method, called recSize, that takes no parameters and returns an integer containing the total number of elements in the doubly-linked list. Use a strategy similar to the previous problem.

You must implement programming #2 and #3 recursively, not iteratively, to get any credit. You can check to make sure your methods are recursive by seeing that the sort only needs one or two non-nested loop constructs, and the count doesn't need any loop constructs at all.