// // QuickSort.java // /* VisAD system for interactive analysis and visualization of numerical data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and Tommy Jasmin. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package visad; /** QuickSort sorts a set of samples in R using a quicksort algorithm combined with an insertion sort algorithm to avoid an excess number of recursive calls.<P> All of QuickSort's variables and methods are static.<P> */ public class QuickSort { // number of elements to sort with insertion sort private static final int CHEAT_NUM = 15; // default number of elements to test in main method private static final int ELEMENTS = 100000; // Insertion Sort private static void insertion(float a[], int[] p, int lo, int hi) throws VisADException { for (int i=lo+1; i<=hi; i++) { int j = i; float B = a[i]; int P = p[i]; while ((j > 0) && (a[j-1] > B)) { a[j] = a[j-1]; p[j] = p[j-1]; j--; } a[j] = B; p[j] = P; } } // version for doubles private static void insertion(double a[], int[] p, int lo, int hi) throws VisADException { for (int i=lo+1; i<=hi; i++) { int j = i; double B = a[i]; int P = p[i]; while ((j > 0) && (a[j-1] > B)) { a[j] = a[j-1]; p[j] = p[j-1]; j--; } a[j] = B; p[j] = P; } } // Quick Sort private static void sort(float a[], int[] p, int lo0, int hi0) throws VisADException { // call the insertion sort if few enough elements if (hi0-lo0 < CHEAT_NUM) { insertion(a, p, lo0, hi0); } else { int lo = lo0; int hi = hi0; // start in the middle float mid = a[(lo0+hi0)/2]; // loop through the array until indices cross while (lo <= hi) { // find lo-most element >= partition element while ( (lo < hi0) && (a[lo] < mid) ) ++lo; // find hi-most element <= partition element while ( (hi > lo0) && (a[hi] > mid) ) --hi; // swap indices if they have not crossed if (lo <= hi) { int P = p[lo]; p[lo] = p[hi]; p[hi] = P; float T = a[lo]; a[lo++] = a[hi]; a[hi--] = T; } } // sort the left partition if necessary if (lo0 < hi) sort(a, p, lo0, hi); // sort the right partition if necessary if (lo < hi0) sort(a, p, lo, hi0); } } // version for doubles private static void sort(double a[], int[] p, int lo0, int hi0) throws VisADException { // call the insertion sort if few enough elements if (hi0-lo0 < CHEAT_NUM) { insertion(a, p, lo0, hi0); } else { int lo = lo0; int hi = hi0; // start in the middle double mid = a[(lo0+hi0)/2]; // loop through the array until indices cross while (lo <= hi) { // find lo-most element >= partition element while ( (lo < hi0) && (a[lo] < mid) ) ++lo; // find hi-most element <= partition element while ( (hi > lo0) && (a[hi] > mid) ) --hi; // swap indices if they have not crossed if (lo <= hi) { int P = p[lo]; p[lo] = p[hi]; p[hi] = P; double T = a[lo]; a[lo++] = a[hi]; a[hi--] = T; } } // sort the left partition if necessary if (lo0 < hi) sort(a, p, lo0, hi); // sort the right partition if necessary if (lo < hi0) sort(a, p, lo, hi0); } } /** * Sort the array in place and return an array of the * orginal indices. * @param a array of floats to sort * @return array of the original indices of each element of a. */ public static int[] sort(float a[]) throws VisADException { int[] p = new int[a.length]; for (int i=0; i<a.length; i++) p[i] = i; sort(a, p, 0, a.length-1); return p; } /** * Sort the array in place and return an array of the * orginal indices. * @param a array of doubles to sort * @return array of the original indices of each element of a. */ public static int[] sort(double a[]) throws VisADException { int[] p = new int[a.length]; for (int i=0; i<a.length; i++) p[i] = i; sort(a, p, 0, a.length-1); return p; } /** * Sort the array in place and return an array of the * orginal indices. * @param a array of floats to sort * @param start to stop (inclusive) * @return array of the original indices of each element of a. */ public static int[] sort(float a[], int start, int stop) throws VisADException { int[] p = new int[a.length]; for (int i=0; i<a.length; i++) p[i] = i; sort(a, p, start, stop); return p; } /** * Sort the array in place and return an array of the * orginal indices. * @param a array of doubles to sort * @param start to stop (inclusive) * @return array of the original indices of each element of a. */ public static int[] sort(double a[], int start, int stop) throws VisADException { int[] p = new int[a.length]; for (int i=0; i<a.length; i++) p[i] = i; sort(a, p, start, stop); return p; } /* run 'java visad.QuickSort [elements]' to test the QuickSort class. [elements] defaults to 100000, or you can specify your own value. */ public static void main(String[] argv) throws VisADException { int elements = ELEMENTS; if (argv.length > 0) { try { elements = Integer.parseInt(argv[0]); } catch (Exception e) { System.out.println("Usage: java visad.QuickSort " +"[number of elements to sort]"); System.exit(1); } } System.out.print("Creating array of "+elements+" random elements..."); long start1 = System.currentTimeMillis(); float[] test = new float[elements]; // make up an array with random elements for (int i=0; i<elements; i++) { test[i] = (float) (1000*Math.random()); } long end1 = System.currentTimeMillis(); float time1 = (float) (end1-start1) /1000; System.out.println("\nCreation of random elements took " +time1+" seconds."); System.out.print("Sorting..."); long start2 = System.currentTimeMillis(); int[] p = sort(test); long end2 = System.currentTimeMillis(); System.out.println("done."); for (int i=1; i<elements; i++) { if (test[i-1] > test[i]) { System.out.println("Error in sort, values not in order!"); System.exit(1); } } float time2 = (float) (end2-start2) /1000; System.out.println("Sort of elements took "+time2+" seconds."); System.exit(0); } /* Here's the output: iris 99% java visad.QuickSort 500000 Creating array of 500000 random elements... Creation of random elements took 11.691 seconds. Sorting...done. Sort of elements took 4.953 seconds. iris 100% */ }