/*
Demo quick sort program with a bug.
QuickSort 10 works correctly
QuickSort 11 doesn't!
*/
package com.lambda.Experiment;
public class QuickSort {
static int MAX;
int[] array;
public static void main(String[] argv) {
int n = 10;
if (argv.length > 0)
n = Integer.parseInt(argv[0]);
sortNElements(n);
}
public static void sortNElements(int nElements) {
MAX = nElements;
System.out
.println("----------------------QuickSort Program----------------------");
QuickSort q = new QuickSort();
q.array = new int[MAX];
q.array[0] = 1;
for (int i = 1; i < MAX; i++)
q.array[i] = ((i - 1) * 1233) % 1974; // More-or-less random
q.sortAll();
q.checkOrder();
q.printAll();
}
public void sortAll() {
Thread t = new Thread(new QuickSortRunnable(this, 0, MAX - 1));
t.start();
try {
t.join();
} catch (InterruptedException ie) {
System.out.println("Impossible");
}
}
public void checkOrder() {
for (int i = 1; i < MAX; i++) {
if (array[i - 1] > array[i])
System.out.println("Out of order: array[" + (i - 1) + "]="
+ array[i - 1] + " > array[" + i + "]=" + array[i]);
}
}
public void printAll() {
int top = MAX;
if (MAX > 100)
top = 100;
for (int i = 0; i < top; i++) {
System.out.println(i + "\t " + array[i]);
}
}
// **** This will be called recursively and from different threads. ****
public void sort(int start, int end) {
int i, j, tmp, average, middle;
if ((end - start) < 1)
return; // One element, done!
if ((end - start) == 1) { // Two elements, sort directly
if (array[end] > array[start])
return;
tmp = array[start];
array[start] = array[end];
array[end] = tmp;
return;
}
average = average(start, end);
middle = end; // This will become the pivot point
L: for (i = start; i < middle; i++) { // Start the pivot:
if (array[i] > average) { // Move all values > average up,
for (j = middle; j > i; j--) {
if (array[j] <= average) { // all values <= average down.
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
middle = j; // The pivot point remains in the middle
continue L;
}
}
}
}
Thread t = null; // Make a new thread to do bottom half of sort
t = new Thread(new QuickSortRunnable(this, start, middle - 1));
t.start();
sort(middle, end); // Do the top half here.
try {
t.join();
} // Wait for the bottom half to finish
catch (InterruptedException ie) {
System.out.println("Impossible");
}
return;
}
public int average(int start, int end) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return (sum / (end - start));
}
}
// **************** Just a wrapper for threads ****************
class QuickSortRunnable implements Runnable {
private int start, end;
private QuickSort sorter;
public QuickSortRunnable(QuickSort qs, int start, int end) {
this.start = start;
this.end = end;
this.sorter = qs;
}
public void run() {
sorter.sort(start, end);
}
}