[*] T(n) = 2T(n/2) + cost of merging two sorted lists
<MergeSort>=
public void mergeSort(String[] words, int first, int last) {
if (first < last) {
int middle = (first+last)/2;
mergeSort(words, first, middle);
mergeSort(words, middle+1, last);
<Merge the two sorted short lists into a longer one>
}
}
To complete the recurrence relation for merge sort, we must determine how to merge to sorted lists and how much it costs to do so. The code below come from Sedgewick [cite sedg:88]. The basic idea is to move the first half of the words[] into a the first half of a tempWords[] array, and the last half of the words[] into a the last half of tempWords[], but in reverse order (this is Sedgewick's ``trick.'' It leads to a simple coding loop).
Also note that tempWords[] is indexed from 0 to last-first, while words[] is indexed from first] to last]. We'll let our for] loops range from first] to last] and subtract first] from all indexes into tempWords[].
<Merge the two sorted short lists into a longer one>= (<-U) String[] tempWords = new String[last-first+1]; <Move first half of words[] into first half of tempWords[]> <Reverse last half of words[] when moving to tempWords[]> <Move tempWords[], from the low or high ends, back into words]>
Move the first half of words[] into tempWords[].
<Move first half of words[] into first half of tempWords[]>= (<-U)
for (int i = first; i <= middle; i++) {
tempWords[i-first] = words[i];
}
Here's the build-up to the trick: when moving the last of half of words[] into tempWords[], reverse their order.
<Reverse last half of words[] when moving to tempWords[]>= (<-U)
for (int i = middle; i < last; i++) {
tempWords[last+middle-i-first] = words[i+1];
}
And here's the application of the trick. Keep indices to the low and high ends of array tempWords[], and whenever the low word is less than the high word, write down the low and increment low to point to the next word. Otherwise, write down the high word and decrement high.
<Move tempWords[], from the low or high ends, back into words>=
int low = 0;
int high = last-first;
for (int k = first; k <= last; k++) {
<When tempWords[low] < tempWords[high] write tempWords[low]>
else { <Write tempWords[high]> }
}
The Java compareTo() function for String variables makes the comparison. When the low word is smaller, we write it back into words[] at the current position k.
<When tempWords[low] < tempWords[high] write tempWords[low]>= (<-U)
if (tempWords[low].compareTo(tempWords[high]) < 0) {
words[k] = tempWords[low];
++low;
}
When the high word is smaller (or equal), we write it back into words[] at the current position k.
<Write tempWords[high]>= (<-U) words[k] = tempWords[high]; --high;