Comp 271 Week 5

Mergesort
Quicksort

Timings

Here are my timing runs for selection and insertion sort when run from bluej:
    5.042 sec   2.89 sec
    5.037 sec   2.873 sec
    1.802 sec   0.438 sec
    1.803 sec   0.44 sec
These exhibit the "third run" phenomenon: times don't really settle down until the third run.

I modified the program to run as a standalone java application. When I did that, I got numbers like the following:
    3.745 sec    3.121 sec
    3.744 sec    3.11 sec
    1.836 sec    0.444 sec
    1.832 sec    0.442 sec
As you can see, the stand-alone times started out with selection sort running faster and insertion sort running slower. However, upon the third run, they were essentially identical with the bluej numbers.

I attribute this to Java Virtual Machine optimizations that are done "on the fly".

Merge sort (p 127)

Basic idea: split, and merge.

One strategy: merge into a temp array T, then copy back into A.

Book's strategy: a little different; requires copying only half  the array. How much does this slow things down? One way to investigate this would be to copy the entire array twice, to see the speedup.

Another strategy for reducing the copying of T is the "back-and-forth" method: merging from A into T at one stage, and then from T into A at the next. This is easier for the nonrecursive version.

Count comparisons: log(n) steps, and all the merges at each step take O(n) together (more precisely, we have to merge lists whose total length is n). Total: O(n log n)

IterativeMergeSort: how it works. Issues with merge.

The optimization to avoid copying

Thursday

1. Change to RecursiveMergeSort to make it a little easier to use the merge code directly in IterativeMergeSort

2. Compare
    T[k]=A[i];
    k++;
    i++;
with
    T[k++] = A[i++];


Quicksort (p 131)

The first sentence of section 6.5 is remarkably opaque! Also, the idea that speed depends on getting values to their ultimate location early on is demonstrably false; see mergesort.

Problem with quicksort2: attempting to use the median as pivot value, or for that matter attempting to use a value not in the array as pivot. One solution is to use data[mid] as the pivot; that works well with previously sorted data.

Consider the following array of data:
3
11
8
18
7
14
5
13

Suppose we use 11 as the pivot value.
    Decrement right until it points to 5
    Swap 11 and 5: 3 5 8 18 7 14 11 13
    increment left until it points to 18
    Swap 18 and 11: 3 5 8 11 7 14 18 13
    decrement right until it points to 7
    swap 11 and 7: 3 5 8 7 11 14 18 13
Now the array is divided into elements < 11, 11 itself, and elements > 11.

Suppose we use 10 as pivot value.
    Decrement right to 5
    increment left to 11, swap: 3 5 8 18 7 14 11 13
    decrement right to 7
    increment left to 18, swap: 3 5 8 7 18 14 11 13

Now the array is divided into two segments, those < 10 and those > 10.

Problem: what if A[lo] is just a bad pivot value? This is a real concern; often one wants to minimize ones exposure to the "worst case".

Possible solutions:
Picking an element at random. This is safe, though nondeterministic.

Pivoting on, say, (a[lo]+a[hi])/2. If this is equal to a[hi], then it is a safe pivot. Otherwise, when we pivot, the "upper half" is definitely nonempty. But if we take a two-element array, say (5 6), then the pivot is 5


Radix Sort (p 134)

Basic algorithm

What if we did the bucketing in high-to-low order? (most-significant to least-significant digit)

Is this O(n)? (answer: no)

First look at linked lists

Suppose we define
    class Cell {
       private String data;
       private Cell next;
       Cell(String s, Cell n) {data = s; next = n;}
       String data() {return this.data;}
       Cell next(() {return this.next;}
    }

What can we do with this? Here is an empty list:
    L = null

Here is a one-element list:
    L = new Cell("cherry", L)

How about this? In what order do they get added?
    L = new Cell("blueberry", L);
    L = new Cell("apricot", L);

What does this loop do?
    Cell p = L;
    while (p!= null) {
          System.out.println(p.data());
          p = p.next();
    }