merge(Comparable[] a, Comparable[] tmpArray, int leftPos, int rightPos, int rightEnd) { see below for content }
a[leftPos .. rightEnd]
a[leftPos .. (rightPos-1)]
a[rightPost .. rightEnd]
a[]: . . . --+---+---+---+---+---+---+---+---+---+---+---+---+-- . . . . . . . | . | . | A | E | K | R | C | H | U | Z | . | . | . . . . . . . --+---+---+---+---+---+---+---+---+---+---+---+---+-- . . . lp rp re
merge()
tmpArray[]
/** * method that merges two sorted halves of a subarray. * @param |a| an array of |Comparable| items. * @param |tmpArray| an array to place the merged result. * @param |leftPos| the left-most index of the subarray. * @param |rightPos| the index of the start of the second half. * @param |rightEnd| the right-most index of the subarray. * @author Mark Allen Weiss. */ void merge( Comparable [ ] a, Comparable [ ] tmpArray, int leftPos, int rightPos, int rightEnd ) { int leftEnd = rightPos - 1; int tmpPos = leftPos; int numElements = rightEnd - leftPos + 1; // Main loop while( leftPos <= leftEnd && rightPos <= rightEnd ) if( a[ leftPos ].compareTo( a[ rightPos ] ) <= 0 ) tmpArray[ tmpPos++ ] = a[ leftPos++ ]; else tmpArray[ tmpPos++ ] = a[ rightPos++ ]; while( leftPos <= leftEnd ) // Copy rest of first half tmpArray[ tmpPos++ ] = a[ leftPos++ ]; while( rightPos <= rightEnd ) // Copy rest of right half tmpArray[ tmpPos++ ] = a[ rightPos++ ]; // Copy tmpArray back for( int i = 0; i < numElements; i++, rightEnd-- ) a[ rightEnd ] = tmpArray[ rightEnd ]; }
a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp rp re merge(Comparable[] a, Comparable[] tmpArray, int leftPos, int rightPos, int rightEnd) { int leftEnd = rightPos - 1 ; int tmpPos = leftPos ; int numElements = rightEnd - leftPos + 1 ; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp le rp re tp // the code 'marches' |leftPos| and |rightPos| // through left half and right half of array, respectively, // until reach |leftEnd| and |rightEnd|, respectively; // at each moment copy next smallest element // from either left half or right half into |tmpArray[]| // Main loop while ( leftPos <= leftEnd && rightPos <= rightEnd ) if ( a[leftPos].compareTo(a[rightPos]) <= 0 ) tmpArray[tmpPos++ ] = a[leftPos++ ] ; else tmpArray[tmpPos++] = a[rightPos++]; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"| | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp le rp re tp while ( leftPos <= leftEnd && rightPos <= rightEnd ) if ( a[leftPos].compareTo(a[rightPos]) <= 0 ) tmpArray[tmpPos++] = a[leftPos++]; else tmpArray[tmpPos++] = a[rightPos++] ; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"| | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp le rp re tp while ( leftPos <= leftEnd && rightPos <= rightEnd ) if ( a[leftPos].compareTo(a[rightPos]) <= 0 ) tmpArray[tmpPos++] = a[leftPos++] ; else tmpArray[tmpPos++] = a[rightPos++]; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"| | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp le rp re tp while ( leftPos <= leftEnd && rightPos <= rightEnd ) if ( a[leftPos].compareTo(a[rightPos]) <= 0 ) tmpArray[tmpPos++] = a[leftPos++]; else tmpArray[tmpPos++] = a[rightPos++] ; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"|"H"| | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 lp le rp re tp while ( leftPos <= leftEnd && rightPos <= rightEnd ) a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"|"H"|"K"| | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 le rp re tp lp while ( leftPos <= leftEnd && rightPos <= rightEnd ) a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"|"H"|"K"|"R"| | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 le rp re tp lp while ( leftPos <= leftEnd && rightPos <= rightEnd ) // so conclude executing that loop // next: while ( leftPos <= leftEnd ) // Copy rest of first half tmpArray[tmpPos++] = a[leftPos++]; while ( rightPos <= rightEnd ) // Copy rest of right half tmpArray[tmpPos++] = a[rightPos++]; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"|"H"|"K"|"R"|"U"| | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 le re tp lp rp while ( rightPos <= rightEnd ) // Copy rest of right half tmpArray[tmpPos++] = a[rightPos++]; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"E"|"K"|"R"|"C"|"H"|"U"|"Z"| |"A"|"C"|"E"|"H"|"K"|"R"|"U"|"Z"| +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 le re tp lp rp while ( rightPos <= rightEnd ) // so conclude executing that loop // Copy tmpArray[] back for ( int i = 0; i < numElements; i++, rightEnd-- ) a[rightEnd] = tmpArray[rightEnd]; a[]: tmpArray[]: +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ |"A"|"C"|"E"|"H"|"K"|"R"|"U"|"Z"| |"A"|"C"|"E"|"H"|"K"|"R"|"U"|"Z"| +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 re re } // end |merge()|
mergeSort()
mergeSort(Comparable[] a) { Comparable[] tmpArray = new Comparable[a.length]; mergeSort(a, tmpArray, 0, a.length - 1); } mergeSort(Comparable[] a, Comparable[] tmpArray, int left, int right) { if ( left < right ) { int center = (left + right) / 2; mergeSort(a, tmpArray, left, center); mergeSort(a, tmpArray, center + 1, right); merge(a, tmpArray, left, center + 1, right); } }
level-0 invocation of mergeSort() gets initial data: +---+---+---+---+---+---+---+---+ | K | E | R | A | H | Z | U | C | +---+---+---+---+---+---+---+---+ first level-1 recursive invocation will work on first half: +---+---+---+---+---+---+---+---+ | K | E | R | A | . | . | . | . | +---+---+---+---+---+---+---+---+ first level-2 recursive invocation here will work on first sub-half i.e. first quarter: +---+---+---+---+---+---+---+---+ | K | E | . | . | . | . | . | . | +---+---+---+---+---+---+---+---+ yielding the following: +---+---+---+---+---+---+---+---+ | E | K | . | . | . | . | . | . | +---+---+---+---+---+---+---+---+ second level-2 recursive invocation here will work on second sub-half i.e. second quarter: +---+---+---+---+---+---+---+---+ | . | . | R | A | . | . | . | . | +---+---+---+---+---+---+---+---+ yielding the following: +---+---+---+---+---+---+---+---+ | . | . | A | R | . | . | . | . | +---+---+---+---+---+---+---+---+ currently things appear as follows: +---+---+---+---+---+---+---+---+ | E | K | A | R | . | . | . | . | +---+---+---+---+---+---+---+---+ then merge() yields the following: +---+---+---+---+---+---+---+---+ | A | E | K | R | . | . | . | . | +---+---+---+---+---+---+---+---+ second level-1 recursive invocation will work on second half: +---+---+---+---+---+---+---+---+ | . | . | . | . | H | Z | U | C | +---+---+---+---+---+---+---+---+ first level-2 recursive invocation here will work on first sub-half here: +---+---+---+---+---+---+---+---+ | . | . | . | . | H | Z | . | . | +---+---+---+---+---+---+---+---+ (not much to do here) second level-2 recursive invocation here will work on second sub-half here: +---+---+---+---+---+---+---+---+ | . | . | . | . | . | . | U | C | +---+---+---+---+---+---+---+---+ yielding the following: +---+---+---+---+---+---+---+---+ | . | . | . | . | . | . | C | U | +---+---+---+---+---+---+---+---+ then the HZ.. and ..CU need to be merged, yielding: +---+---+---+---+---+---+---+---+ | . | . | . | . | C | H | U | Z | +---+---+---+---+---+---+---+---+ then the AEKR.... and ....CHUZ need to be merged, yielding: +---+---+---+---+---+---+---+---+ | A | C | E | H | K | R | U | Z | +---+---+---+---+---+---+---+---+
leftPos
rightPos
tmpPos
a[]
i
rightEnd
mergeSort() merge(): N total work at this level: N +---+---+---+---+---+---+---+---+ | K | E | R | A | H | Z | U | C | +---+---+---+---+---+---+---+---+
mergeSort() mergeSort() merge(): N/2 merge(): N/2 total: +---+---+---+---+---+---+---+---+ | K | E | R | A | H | Z | U | C | +---+---+---+---+---+---+---+---+
mergeSort(): mergeSort(): ms() ms() ms() ms() m():N/4 m():N/4 m():N/4 m():N/4 total: +---+---+---+---+---+---+---+---+ | K | E | R | A | H | Z | U | C | +---+---+---+---+---+---+---+---+ and so on
quickSort(Comparable[] a, int left, int right) { H U G H W I N G F I E L D M C G U I R E 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 l r // see discussion of CUTOFF below Comparable pivot = median3(a, left, right) { /** * Return median of left, center, and right. * Order these and hide the pivot. */ int center = (left + right)/2; H . . . . . . . . I . . . . . . . . . E 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 l c r if ( a[center].compareTo(a[left]) < 0 ) swapReferences(a, left, center); H . . . . . . . . I . . . . . . . . . E l c r // if original material was x...y...z, // then |a[left]| now contains min{x,y} if ( a[right].compareTo(a[left]) < 0 ) swapReferences(a, left, right); E . . . . . . . . I . . . . . . . . . H l c r // that compared z which was |a[right]| to // |a[left]| which was min{x,y} // and if z < min{x,y}, put z in |a[left]| // so now |a[left]| contains smallest of {x,y,z} // and |a[center]|, |a[right]| contain largest two of the values // the next chunk of code puts a[center],a[right] in order: if ( a[right].compareTo(a[center]) < 0 ) swapReferences(a, center, right); E . . . . . . . . H . . . . . . . . . I l c r // Place pivot at position right - 1 : E . . . . . . . . H . . . . . . . . R I l c r-1 r swapReferences(a, center, right - 1); E . . . . . . . . R . . . . . . . . H I l c r-1 r return a[right - 1]; } Comparable pivot = median3(a, left, right); // Begin partitioning int i = left, j = right - 1; l r-1 r E U G H W I N G F R E L D M C G U I H I i j for ( ; ; ) { // shift |i| rightward while the element at |i| // is less than the pivot: while ( a[++i].compareTo(pivot) < 0 ) { } E U G H W I N G F R E L D M C G U I H I | j r | first a[++i] i left here // shift |j| leftward while the element at |j| // is greater than the pivot: while ( a[--j].compareTo(pivot) > 0 ) { } E U G H W I N G F R E L D M C G U I H I | | ... | r | | | i left here | first a[--j] j left here if ( i < j ) swapReferences(a, i, j); else break; i j E G G H W I N G F R E L D M C U U I H I } for ( ; ; ) { // shift |i| rightward while the element at |i| // is less than the pivot: while ( a[++i].compareTo(pivot) < 0 ) { } // shift |j| leftward while the element at |j| // is greater than the pivot: while ( a[--j].compareTo(pivot) > 0 ) { } E G G H W I N G F R E L D M C U U I H I i j if ( i < j ) swapReferences(a, i, j); else break; i j E G G C W I N G F R E L D M H U U I H I } for ( ; ; ) { while ( a[++i].compareTo(pivot) < 0 ) { } while ( a[--j].compareTo(pivot) > 0 ) { } E G G C W I N G F R E L D M H U U I H I i j if ( i < j ) swapReferences(a, i, j); else break; i j E G G C D I N G F R E L W M H U U I H I } for ( ; ; ) { while ( a[++i].compareTo(pivot) < 0 ) { } while ( a[--j].compareTo(pivot) > 0 ) { } E G G C D I N G F R E L W M H U U I H I i j if ( i < j ) swapReferences(a, i, j); else break; i j E G G C D E N G F R I L W M H U U I H I } for ( ; ; ) { while ( a[++i].compareTo(pivot) < 0 ) { } while ( a[--j].compareTo(pivot) > 0 ) { } E G G C D E N G F R I L W M H U U I H I i j if ( i < j ) swapReferences(a, i, j); else break; i j E G G C D E F G N R I L W M H U U I H I } for ( ; ; ) { while ( a[++i].compareTo(pivot) < 0 ) { } E G G C D E F G N R I L W M H U U I H I i j while ( a[--j].compareTo(pivot) > 0 ) { } E G G C D E F G N R I L W M H U U I H I i j if ( i < j ) swapReferences(a, i, j); else break; } swapReferences(a, i, right - 1); // Restore pivot i j r-1 r E G G C D E F G H R I L W M H U U I N I quicksort(a, left, i - 1) { // Sort small elements i l i-1 i E G G C D E F G . . . . . . . . . . . . // yields: C D E E F G G G . . . . . . . . . . . . } quicksort(a, i + 1, right) { // Sort large elements i i+1 r . . . . . . . . . R I L W M H U U I N I // yields: . . . . . . . . . H I I I L M N R U U W } // showing all the elements at this point, things are as follows: C D E E F G G G H H I I I L M N R U U W
for ( ; ; )
while ( a[++i] )
while ( a[--j] )
if ( i < j )
H U G H W I N G F I E L D M C G U I R E C U G H W I N G F I E L D M H G U I R E
. U G H W I N G F I E L D M H G U I R E
. D G H W I N G F I E L U M H G U I R E
. . G H W I N G F I E L U M H G U I R E . . E E W I N G F I H L U M H G U I R G . . . . W I N G F I H L U M H G U I R G