Mega Code Archive

 
Categories / Java / Collections Data Structure
 

A quick sort algorithm to sort Vectors or arrays Provides sort and binary search capabilities

// HTMLParser Library - A java-based parser for HTML // http://htmlparser.org // Copyright (C) 2006 Derrick Oswald // // Revision Control Information // // $URL: https://svn.sourceforge.net/svnroot/htmlparser/trunk/lexer/src/main/java/org/htmlparser/util/sort/Sort.java $ // $Author: derrickoswald $ // $Date: 2006-09-16 10:44:17 -0400 (Sat, 16 Sep 2006) $ // $Revision: 4 $ // // This library is free software; you can redistribute it and/or // modify it under the terms of the Common Public License; either // version 1.0 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 // Common Public License for more details. // // You should have received a copy of the Common Public License // along with this library; if not, the license is available from // the Open Source Initiative (OSI) website: //   http://opensource.org/licenses/cpl1.0.php //package org.htmlparser.util.sort; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; /**  * A quick sort algorithm to sort Vectors or arrays. Provides sort and binary  * search capabilities.  * <p>  * This all goes away in JDK 1.2.  * <p>  *   * @author James Gosling  * @author Kevin A. Smith  * @author Derrick Oswald  * @version 1.4, 11 June, 1997  */ public class Sort {   /**    * No object of this class need ever be instantiated. All methods are    * static.    */   private Sort() {   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle vectors that are already sorted, and vectors with duplicate    * keys. Equivalent to:    *     * <pre>    * QuickSort(v, 0, v.size() - 1);    * </pre>    *     * @param v    *            A <code>Vector</code> of <code>Ordered</code> items.    * @exception ClassCastException    *                If the vector contains objects that are not    *                <code>Ordered</code>.    */   public static void QuickSort(Vector v) throws ClassCastException {     QuickSort(v, 0, v.size() - 1);   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle vectors that are already sorted, and vectors with duplicate    * keys.    * <p>    * If you think of a one dimensional vector as going from the lowest index    * on the left to the highest index on the right then the parameters to this    * function are lowest index or left and highest index or right.    *     * @param v    *            A <code>Vector</code> of <code>Ordered</code> items.    * @param lo0    *            Left boundary of vector partition.    * @param hi0    *            Right boundary of vector partition.    * @exception ClassCastException    *                If the vector contains objects that are not    *                <code>Ordered</code>.    */   public static void QuickSort(Vector v, int lo0, int hi0)       throws ClassCastException {     int lo = lo0;     int hi = hi0;     Ordered mid;     if (hi0 > lo0) { // arbitrarily establish partition element as the               // midpoint of the vector       mid = (Ordered) v.elementAt((lo0 + hi0) / 2);       // loop through the vector until indices cross       while (lo <= hi) {         // find the first element that is greater than or equal to         // the partition element starting from the left index         while ((lo < hi0)             && (0 > ((Ordered) v.elementAt(lo)).compare(mid)))           ++lo;         // find an element that is smaller than or equal to         // the partition element starting from the right index         while ((hi > lo0)             && (0 < ((Ordered) v.elementAt(hi)).compare(mid)))           --hi;         // if the indexes have not crossed, swap         if (lo <= hi)           swap(v, lo++, hi--);       }       // if the right index has not reached the left side of array       // must now sort the left partition       if (lo0 < hi)         QuickSort(v, lo0, hi);       // if the left index has not reached the right side of array       // must now sort the right partition       if (lo < hi0)         QuickSort(v, lo, hi0);     }   }   private static void swap(Vector v, int i, int j) {     Object o;     o = v.elementAt(i);     v.setElementAt(v.elementAt(j), i);     v.setElementAt(o, j);   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle arrays that are already sorted, and arrays with duplicate    * keys.    * <p>    * Equivalent to:    *     * <pre>    * QuickSort(a, 0, a.length - 1);    * </pre>    *     * @param a    *            An array of <code>Ordered</code> items.    */   public static void QuickSort(Ordered[] a) {     QuickSort(a, 0, a.length - 1);   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle arrays that are already sorted, and arrays with duplicate    * keys.    * <p>    * If you think of a one dimensional array as going from the lowest index on    * the left to the highest index on the right then the parameters to this    * function are lowest index or left and highest index or right.    *     * @param a    *            An array of <code>Ordered</code> items.    * @param lo0    *            Left boundary of array partition.    * @param hi0    *            Right boundary of array partition.    */   public static void QuickSort(Ordered[] a, int lo0, int hi0) {     int lo = lo0;     int hi = hi0;     Ordered mid;     if (hi0 > lo0) {       // arbitrarily establish partition element as the midpoint of the       // array       mid = a[(lo0 + hi0) / 2];       // loop through the vector until indices cross       while (lo <= hi) {         // find the first element that is greater than or equal to         // the partition element starting from the left index         while ((lo < hi0) && (0 > a[lo].compare(mid)))           ++lo;         // find an element that is smaller than or equal to         // the partition element starting from the right Index.         while ((hi > lo0) && (0 < a[hi].compare(mid)))           --hi;         // if the indexes have not crossed, swap         if (lo <= hi)           swap(a, lo++, hi--);       }       // if the right index has not reached the left side of array       // must now sort the left partition       if (lo0 < hi)         QuickSort(a, lo0, hi);       // if the left index has not reached the right side of array       // must now sort the right partition       if (lo < hi0)         QuickSort(a, lo, hi0);     }   }   /**    * Swaps two elements of an array.    *     * @param a    *            The array of elements.    * @param i    *            The index of one item to swap.    * @param j    *            The index of the other item to swap.    */   private static void swap(Object[] a, int i, int j) {     Object o;     o = a[i];     a[i] = a[j];     a[j] = o;   }   /**    * This is a string version of C.A.R Hoare's Quick Sort algorithm. This will    * handle arrays that are already sorted, and arrays with duplicate keys.    * <p>    * Equivalent to:    *     * <pre>    * QuickSort(a, 0, a.length - 1);    * </pre>    *     * @param a    *            An array of <code>String</code> items.    */   public static void QuickSort(String[] a) {     QuickSort(a, 0, a.length - 1);   }   /**    * This is a string version of C.A.R Hoare's Quick Sort algorithm. This will    * handle arrays that are already sorted, and arrays with duplicate keys.    * <p>    * If you think of a one dimensional array as going from the lowest index on    * the left to the highest index on the right then the parameters to this    * function are lowest index or left and highest index or right.    *     * @param a    *            An array of <code>String</code> items.    * @param lo0    *            Left boundary of array partition.    * @param hi0    *            Right boundary of array partition.    */   public static void QuickSort(String[] a, int lo0, int hi0) {     int lo = lo0;     int hi = hi0;     String mid;     if (hi0 > lo0) {       // arbitrarily establish partition element as the midpoint of the       // array       mid = a[(lo0 + hi0) / 2];       // loop through the vector until indices cross       while (lo <= hi) {         // find the first element that is greater than or equal to         // the partition element starting from the left index         while ((lo < hi0) && (0 > a[lo].compareTo(mid)))           ++lo;         // find an element that is smaller than or equal to         // the partition element starting from the right Index.         while ((hi > lo0) && (0 < a[hi].compareTo(mid)))           --hi;         // if the indexes have not crossed, swap         if (lo <= hi)           swap(a, lo++, hi--);       }       // if the right index has not reached the left side of array       // must now sort the left partition       if (lo0 < hi)         QuickSort(a, lo0, hi);       // if the left index has not reached the right side of array       // must now sort the right partition       if (lo < hi0)         QuickSort(a, lo, hi0);     }   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle Sortable objects that are already sorted, and Sortable    * objects with duplicate keys.    * <p>    *     * @param sortable    *            A <code>Sortable</code> object.    * @param lo0    *            Left boundary of partition.    * @param hi0    *            Right boundary of partition.    */   public static void QuickSort(Sortable sortable, int lo0, int hi0) {     int lo = lo0;     int hi = hi0;     Ordered mid;     Ordered test;     if (hi0 > lo0) { // arbitrarily establish partition element as the               // midpoint of the vector       mid = sortable.fetch((lo0 + hi0) / 2, null);       test = null;       // loop through the vector until indices cross       while (lo <= hi) {         // find the first element that is greater than or equal to         // the partition element starting from the left index         while ((lo < hi0)             && (0 > (test = sortable.fetch(lo, test)).compare(mid)))           ++lo;         // find an element that is smaller than or equal to         // the partition element starting from the right index         while ((hi > lo0)             && (0 < (test = sortable.fetch(hi, test)).compare(mid)))           --hi;         // if the indexes have not crossed, swap         if (lo <= hi)           sortable.swap(lo++, hi--);       }       // if the right index has not reached the left side of array       // must now sort the left partition       if (lo0 < hi)         QuickSort(sortable, lo0, hi);       // if the left index has not reached the right side of array       // must now sort the right partition       if (lo < hi0)         QuickSort(sortable, lo, hi0);     }   }   /**    * This is a generic version of C.A.R Hoare's Quick Sort algorithm. This    * will handle Sortable objects that are already sorted, and Sortable    * objects with duplicate keys.    * <p>    * Equivalent to:    *     * <pre>    * QuickSort(sortable, sortable.first(), sortable.last());    * </pre>    *     * @param sortable    *            A <code>Sortable</code> object.    */   public static void QuickSort(Sortable sortable) {     QuickSort(sortable, sortable.first(), sortable.last());   }   /**    * Sort a Hashtable.    *     * @param h    *            A Hashtable with String or Ordered keys.    * @return A sorted array of the keys.    * @exception ClassCastException    *                If the keys of the hashtable are not <code>Ordered</code>.    */   public static Object[] QuickSort(Hashtable h) throws ClassCastException {     Enumeration e;     boolean are_strings;     Object[] ret;     // make the array     ret = new Ordered[h.size()];     e = h.keys();     are_strings = true; // until proven otherwise     for (int i = 0; i < ret.length; i++) {       ret[i] = e.nextElement();       if (are_strings && !(ret[i] instanceof String))         are_strings = false;     }     // sort it     if (are_strings)       QuickSort((String[]) ret);     else       QuickSort((Ordered[]) ret);     return (ret);   }   /**    * Binary search for an object    *     * @param set    *            The collection of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @param lo    *            The lower index within which to look.    * @param hi    *            The upper index within which to look.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Sortable set, Ordered ref, int lo, int hi) {     int num;     int mid;     Ordered ordered;     int half;     int result;     int ret;     ret = -1;     num = (hi - lo) + 1;     ordered = null;     while ((-1 == ret) && (lo <= hi)) {       half = num / 2;       mid = lo + ((0 != (num & 1)) ? half : half - 1);       ordered = set.fetch(mid, ordered);       result = ref.compare(ordered);       if (0 == result)         ret = mid;       else if (0 > result) {         hi = mid - 1;         num = ((0 != (num & 1)) ? half : half - 1);       } else {         lo = mid + 1;         num = half;       }     }     if (-1 == ret)       ret = lo;     return (ret);   }   /**    * Binary search for an object    *     * @param set    *            The collection of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Sortable set, Ordered ref) {     return (bsearch(set, ref, set.first(), set.last()));   }   /**    * Binary search for an object    *     * @param vector    *            The vector of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @param lo    *            The lower index within which to look.    * @param hi    *            The upper index within which to look.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Vector vector, Ordered ref, int lo, int hi) {     int num;     int mid;     int half;     int result;     int ret;     ret = -1;     num = (hi - lo) + 1;     while ((-1 == ret) && (lo <= hi)) {       half = num / 2;       mid = lo + ((0 != (num & 1)) ? half : half - 1);       result = ref.compare(vector.elementAt(mid));       if (0 == result)         ret = mid;       else if (0 > result) {         hi = mid - 1;         num = ((0 != (num & 1)) ? half : half - 1);       } else {         lo = mid + 1;         num = half;       }     }     if (-1 == ret)       ret = lo;     return (ret);   }   /**    * Binary search for an object    *     * @param vector    *            The vector of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Vector vector, Ordered ref) {     return (bsearch(vector, ref, 0, vector.size() - 1));   }   /**    * Binary search for an object    *     * @param array    *            The array of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @param lo    *            The lower index within which to look.    * @param hi    *            The upper index within which to look.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Ordered[] array, Ordered ref, int lo, int hi) {     int num;     int mid;     int half;     int result;     int ret;     ret = -1;     num = (hi - lo) + 1;     while ((-1 == ret) && (lo <= hi)) {       half = num / 2;       mid = lo + ((0 != (num & 1)) ? half : half - 1);       result = ref.compare(array[mid]);       if (0 == result)         ret = mid;       else if (0 > result) {         hi = mid - 1;         num = ((0 != (num & 1)) ? half : half - 1);       } else {         lo = mid + 1;         num = half;       }     }     if (-1 == ret)       ret = lo;     return (ret);   }   /**    * Binary search for an object    *     * @param array    *            The array of <code>Ordered</code> objects.    * @param ref    *            The name to search for.    * @return The index at which reference was found or is to be inserted.    */   public static int bsearch(Ordered[] array, Ordered ref) {     return (bsearch(array, ref, 0, array.length - 1));   } } // HTMLParser Library - A java-based parser for HTML // http://htmlparser.org // Copyright (C) 2006 Derrick Oswald // // Revision Control Information // // $URL: // https://svn.sourceforge.net/svnroot/htmlparser/trunk/lexer/src/main/java/org/htmlparser/util/sort/Ordered.java // $ // $Author: derrickoswald $ // $Date: 2006-09-16 10:44:17 -0400 (Sat, 16 Sep 2006) $ // $Revision: 4 $ // // This library is free software; you can redistribute it and/or // modify it under the terms of the Common Public License; either // version 1.0 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 // Common Public License for more details. // // You should have received a copy of the Common Public License // along with this library; if not, the license is available from // the Open Source Initiative (OSI) website: // http://opensource.org/licenses/cpl1.0.php /**  * Describes an object that knows about ordering. Implementors must have a  * comparison function, which imposes a partial ordering on some collection of  * objects. Ordered objects can be passed to a sort method (such as  * org.htmlparser.util.sort.Sort) to allow precise control over the sort order.  * <p>  * An set of elements S is partially ordered if and only if  * <code>e1.compare(e2)==0</code> implies that <code>e1.equals(e2)</code> for  * every e1 and e2 in S.  * <p>  * This all goes away in JDK 1.2.  * <p>  * For use with java.lang.Comparable from JDK 1.2:  *   * <pre>  * public int compare(Object o1, Object o2) {  *   return (((Ordered) o1).compare(o2));  * }  * </pre>  *   * @see Sort  */ interface Ordered {   /**    * Compares this object with another for order. Returns a negative integer,    * zero, or a positive integer as this object is less than, equal to, or    * greater than the second.    * <p>    * The implementor must ensure that    * <code>sgn(x.compare(y)) == -sgn(y.compare(x))</code> for all x and y.    * (This implies that <code>x.compare(y)</code> must throw an exception if    * and only if <code>y.compare(x)</code> throws an exception.)    * <p>    * The implementor must also ensure that the relation is transitive:    * <code>((x.compare(y)>0) && (y.compare(z)>0))</code> implies    * <code>x.compare(z)>0</code>.    * <p>    * Finally, the implementer must ensure that <code>x.compare(y)==0</code>    * implies that <code>sgn(x.compare(z))==sgn(y.compare(z))</code> for all z.    *     * @param that    *            The object to compare this object against.    * @return A negative integer, zero, or a positive integer as this object is    *         less than, equal to, or greater than the second.    * @exception ClassCastException    *                The arguments type prevents it from being compared by this    *                Ordered.    */   public int compare(Object that); } // HTMLParser Library - A java-based parser for HTML // http://htmlparser.org // Copyright (C) 2006 Derrick Oswald // // Revision Control Information // // $URL: // https://svn.sourceforge.net/svnroot/htmlparser/trunk/lexer/src/main/java/org/htmlparser/util/sort/Sortable.java // $ // $Author: derrickoswald $ // $Date: 2006-09-16 10:44:17 -0400 (Sat, 16 Sep 2006) $ // $Revision: 4 $ // // This library is free software; you can redistribute it and/or // modify it under the terms of the Common Public License; either // version 1.0 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 // Common Public License for more details. // // You should have received a copy of the Common Public License // along with this library; if not, the license is available from // the Open Source Initiative (OSI) website: // http://opensource.org/licenses/cpl1.0.php /**  * Provides a mechanism to abstract the sort process. Classes implementing this  * interface are collections of Ordered objects that are to be sorted by the  * Sort class and are not necessarily Vectors or Arrays of Ordered objects.  *   * @see Sort  */ interface Sortable {   /**    * Returns the first index of the Sortable.    *     * @return The index of the first element.    */   public int first();   /**    * Returns the last index of the Sortable.    *     * @return The index of the last element. If this were an array object this    *         would be (object.length - 1).    */   public int last();   /**    * Fetch the object at the given index.    *     * @param index    *            The item number to get.    * @param reuse    *            If this argument is not null, it is an object acquired from a    *            previous fetch that is no longer needed and may be returned as    *            the result if it makes mores sense to alter and return it than    *            to fetch or create a new element. That is, the reuse object is    *            garbage and may be used to avoid allocating a new object if    *            that would normally be the strategy.    * @return The Ordered object at that index.    */   public Ordered fetch(int index, Ordered reuse);   /**    * Swaps the elements at the given indicies.    *     * @param i    *            One index.    * @param j    *            The other index.    */   public void swap(int i, int j); }