/* * [QuickSort.java] * * Summary: Tony Hoare's QuickSort in Java. * * Copyright: (c) 1996-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 1998-01-01 initial version * 1.1 1998-11-10 add name and address. * 1.2 1998-12-28 JDK 1.2 style Comparator * 1.3 2002-02-19 java.util.Comparator by default. * 1.4 2002-03-30 tidy code. * 1.5 2003-05-30 add dummy private constructor * 1.6 2008-01-01 add generics to comparator */ package com.mindprod.quicksort; import java.util.Comparator; import static java.lang.System.*; /** * Tony Hoare's QuickSort in Java. *

* Eric van Bezooijen was the * original author of this version of QuickSort. I modified * the version he posted to comp.lang.java to use a callback * delegate object. I also made a few optimisations. *

* I have also posted source for HeapSort and RadixSort both * of which run faster than QuickSort. * * @author Roedy Green, Canadian Mind Products * @version 1.6 2008-01-01 add generics to comparator * @since 1998 */ public class QuickSort { private static final boolean DEBUGGING = false; private static final int FIRST_COPYRIGHT_YEAR = 1996; private static final String EmbeddedCopyright = "Copyright: (c) 1996-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; /** * when package released. * * @noinspection UnusedDeclaration */ private static final String RELEASE_DATE = "2008-01-01"; /** * embedded version string. */ @SuppressWarnings( { "UnusedDeclaration" } ) private static final String VERSION_STRING = "1.6"; // callback object we are passed that has // a Comparator( a, b ) method. private Comparator comparator; // pointer to the array of user's objects we are sorting private T[] userArray; /** * dummy constructor to prevent its use. Use static method sort. */ private QuickSort() { } // check if user's array is already sorted private boolean isAlreadySorted() { for ( int i = 1; i < userArray.length; i++ ) { if ( comparator.compare( userArray[ i ], userArray[ i - 1 ] ) < 0 ) { return false; } } return true; } // end isAlreadySorted // Partition by splitting this chunk to sort in two and // get all big elements on one side of the pivot and all // the small elements on the other. private int partition( int lo, int hi ) { // If set were unsorted lo is as good as any other a guess at a suitable mid point. // If set were almost sorted, (lo+hi/2) would be a better guess. // I have left it as it was in the original. T pivot = userArray[ lo ]; while ( true ) { // A specialised sort for strings might avoid comparing the the first few common chars to all // Strings in the partition. while ( comparator.compare( userArray[ hi ], pivot ) >= 0 && lo < hi ) { hi--; } while ( comparator.compare( userArray[ lo ], pivot ) < 0 && lo < hi ) { lo++; } if ( lo < hi ) { // exchange objects on either side of the pivot T temp = userArray[ lo ]; userArray[ lo ] = userArray[ hi ]; userArray[ hi ] = temp; } else { return hi; } } // end while } // end partition // recursive quicksort that breaks array up into sub // arrays and sorts each of them. private void quicksort( int p, int r ) { if ( p < r ) { int q = partition( p, r ); if ( q == r ) { q--; } quicksort( p, q ); quicksort( q + 1, r ); } // end if } // end quicksort /** * sort the user's array * * @param userArray Array of Objects to be sorted. * @param comparator Comparator delegate that can compare two Objects and tell which should come first. */ public static void sort( T[] userArray, Comparator comparator ) { QuickSort h = new QuickSort<>(); h.comparator = comparator; h.userArray = userArray; if ( h.isAlreadySorted() ) { return; } h.quicksort( 0, userArray.length - 1 ); if ( h.isAlreadySorted() ) { return; } if ( DEBUGGING ) { // debug ensure sort is working if ( !h.isAlreadySorted() ) { out.println( "Sort failed" ); } } } // end sort } // end class QuickSort