Performs an optimized quicksort of the specified array, using the specified comparator. - Java Data Structure

Java examples for Data Structure:Sort

Description

Performs an optimized quicksort of the specified array, using the specified comparator.

Demo Code


//package com.java2s;
import java.util.*;

public class Main {
    /**/*from  w  w w  .j av a 2  s.  c o  m*/
     * Performs an optimized quicksort of the specified array, using the specified comparator.
     * This method used the same algorithm as used by java.lang.Arrays for sorting arrays of
     * primitive types.  The java.lang.Arrays sort methods for objects, use a merge sort, which
     * is not quite as fast as quicksort.  Note that quicksort is NOT a stable sort, but merge sort is.
     * 
     * @param a
     * @param c
     */
    public static <T> void quickSort(T[] a, Comparator<? super T> c) {
        quickSort(a, 0, a.length, c);
    }

    /**
     * Performs an optimized quicksort of the specified array, using the natural ordering of the object.
     * (They should implement Comparable in order for this method to have any effect.)
     * This method used the same algorithm as used by java.lang.Arrays for sorting arrays of
     * primitive types.  The java.lang.Arrays sort methods for objects, use a merge sort, which
     * is not quite as fast as quicksort.  Note that quicksort is NOT a stable sort, but merge sort is.
     * 
     * @param a
     */
    public static <T> void quickSort(T[] a) {
        quickSort(a, 0, a.length, null);
    }

    public static <T> void quickSort(T[] arr, int offset, int len,
            Comparator<? super T> cmp) {

        final int limit = offset + len;

        // Use an insertion sort for really small arrays.
        if (len < 7) {
            for (int i = offset + 1; i < limit; i++) {
                T v = arr[i];
                int j = i;
                while (j > offset && compare(arr[j - 1], v, cmp) > 0) {
                    arr[j] = arr[j - 1];
                    j--;
                }
                arr[j] = v;
            }
            // Done!
            return;
        }

        // Select a partition element index, m
        int m = offset + (len >> 1);

        int left = offset;
        int right = limit - 1;

        // For arrays > 40, use the pseudomedian of 9
        //
        if (len > 40) {
            int eighthLen = len / 8;
            // Index of median value of the 3 on the left.
            left = medianOf3(arr, left, left + eighthLen, left + 2
                    * eighthLen, cmp);
            // In the middle
            m = medianOf3(arr, m - eighthLen, m, m + eighthLen, cmp);
            // On the right
            right = medianOf3(arr, right - 2 * eighthLen,
                    right - eighthLen, right, cmp);
        }

        // Convert to index of the median of the 3.
        m = medianOf3(arr, left, m, right, cmp);

        T partitionValue = arr[m];

        int a = offset;
        int b = offset;
        int c = limit - 1;
        int d = c;

        while (true) {

            int cmpValue = b <= c ? compare(arr[b], partitionValue, cmp)
                    : 0;

            while (b <= c && cmpValue <= 0) {
                if (cmpValue == 0) {
                    swap(arr, a++, b);
                }
                b++;
                if (b <= c) {
                    cmpValue = compare(arr[b], partitionValue, cmp);
                }
            }

            cmpValue = c >= b ? compare(arr[c], partitionValue, cmp) : 0;

            while (c >= b && cmpValue >= 0) {
                if (cmpValue == 0) {
                    swap(arr, c, d--);
                }
                c--;
                if (c >= b) {
                    cmpValue = compare(arr[c], partitionValue, cmp);
                }
            }

            if (b > c) {
                break;
            }

            swap(arr, b++, c--);
        }

        int s = Math.min(a - offset, b - a);
        vecSwap(arr, offset, b - s, s);

        s = Math.min(d - c, limit - d - 1);
        vecSwap(arr, b, limit - s, s);

        s = b - a;
        if (s > 1) {
            quickSort(arr, offset, s, cmp);
        }

        s = d - c;
        if (s > 1) {
            quickSort(arr, limit - s, s, cmp);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static <T> int compare(T v1, T v2, Comparator<? super T> c) {
        if (c != null) {
            return c.compare(v1, v2);
        }
        if (v1 instanceof Comparable) {
            return ((Comparable) v1).compareTo(v2);
        }
        return 0;
    }

    private static int compare(double d1, double d2, int n1, int n2,
            boolean ascending) {
        int rtn;
        if (Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2)) {
            rtn = 0;
        } else {
            // NaNs are considered to be > than anything else.
            boolean d1NaN = Double.isNaN(d1);
            boolean d2NaN = Double.isNaN(d2);
            if (d1NaN && !d2NaN) {
                rtn = 1;
            } else if (d2NaN && !d1NaN) {
                rtn = -1;
            } else { // Neither can possibly be NaN.
                rtn = d1 < d2 ? -1 : (d1 > d2 ? 1 : 0);
            }
        }
        if (rtn == 0) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static int compare(float d1, float d2, int n1, int n2,
            boolean ascending) {
        int rtn;
        if (Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2)) {
            rtn = 0;
        } else {
            // NaNs are considered to be > than anything else.
            boolean d1NaN = Double.isNaN(d1);
            boolean d2NaN = Double.isNaN(d2);
            if (d1NaN && !d2NaN) {
                rtn = 1;
            } else if (d2NaN && !d1NaN) {
                rtn = -1;
            } else { // Neither can possibly be NaN.
                rtn = d1 < d2 ? -1 : (d1 > d2 ? 1 : 0);
            }
        }
        if (rtn == 0) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static int compare(int d1, int d2, int n1, int n2,
            boolean ascending) {
        int rtn;
        if (d1 == d2) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        } else {
            rtn = d1 < d2 ? -1 : (d1 > d2 ? 1 : 0);
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static int compare(int d1, int d2, double n1, double n2,
            boolean ascending) {
        int rtn;
        if (d1 == d2) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        } else {
            rtn = d1 < d2 ? -1 : (d1 > d2 ? 1 : 0);
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static int compare(int n1, int n2, boolean ascending) {
        int rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static <T extends Comparable<? super T>> int compare(T c1,
            T c2, int n1, int n2, boolean ascending) {
        int rtn = c1.compareTo((T) c2);
        if (rtn == 0) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static <T> int compare(T c1, T c2, Comparator<? super T> c,
            int n1, int n2, boolean ascending) {
        int rtn = c.compare(c1, c2);
        if (rtn == 0) {
            rtn = (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
        }
        if (!ascending)
            rtn = -rtn;
        return rtn;
    }

    private static int compare(int i, int j, int maxDepth, int[]... arrays) {
        for (int d = 0; d < maxDepth; d++) {
            int[] array = arrays[d];
            if (array[i] < array[j])
                return -1;
            if (array[i] > array[i])
                return +1;
        }
        return 0;
    }

    private static int compare(int i, int maxDepth, int[] colBuffer,
            int[]... arrays) {
        for (int d = 0; d < maxDepth; d++) {
            int[] array = arrays[d];
            int bv = colBuffer[d];
            int v = array[i];
            if (bv > v)
                return -1;
            if (bv < v)
                return +1;
        }
        return 0;
    }

    public static int medianOf3(int[] values, int a, int b, int c) {
        int va = values[a];
        int vb = values[b];
        int vc = values[c];
        return va < vb ? (vb < vc ? b : (vc < va ? a : c)) : (va < vc ? a
                : (vc < vb ? b : c));
    }

    /**
     * Given three indexes into the specified array, this method returns the index of the
     * middle element as determined by the supplied comparator.  If the comparator is null,
     * the middle index is determined by the <tt>compareTo</tt> methods of the objects, assuming
     * they implement comparable.
     * 
     * @param a
     * @param x
     * @param y
     * @param z
     * @param c
     * @return
     */
    public static <T> int medianOf3(T[] a, int x, int y, int z,
            Comparator<? super T> c) {
        if (compare(a[x], a[y], c) < 0) {
            // x < y
            if (compare(a[y], a[z], c) < 0) {
                // y < z, so x < y < z
                // y is the middle
                return y;
            }
            // x < y, but y >= z
            if (compare(a[x], a[z], c) < 0) {
                // x < z
                // x < z <= y
                return z;
            }
            // x >= z
            // Has to be x.
            return x;
        }
        // x >= y
        if (compare(a[y], a[z], c) > 1) {
            // y > z
            return y;
        }
        // y <= z
        if (compare(a[x], a[z], c) > 0) {
            // x > z
            return z;
        }
        return x;
    }

    private static <T> void swap(T[] arr, int i, int j) {
        T tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    /**
     * Swaps x[a] with x[b].
     */
    private static void swap(int x[], int a, int b) {
        int t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

    private static void swap(double x[], int[] n, int a, int b) {
        double t = x[a];
        x[a] = x[b];
        x[b] = t;
        int tn = n[a];
        n[a] = n[b];
        n[b] = tn;
    }

    private static void swap(float x[], int[] n, int a, int b) {
        float t = x[a];
        x[a] = x[b];
        x[b] = t;
        int tn = n[a];
        n[a] = n[b];
        n[b] = tn;
    }

    private static void swap(int x[], int[] n, int a, int b) {
        int t = x[a];
        x[a] = x[b];
        x[b] = t;
        t = n[a];
        n[a] = n[b];
        n[b] = t;
    }

    private static <E> void swap(int[] x, E[] n, int a, int b) {
        int t = x[a];
        x[a] = x[b];
        x[b] = t;
        E tmp = n[a];
        n[a] = n[b];
        n[b] = tmp;
    }

    private static void swap(int x[], double[] n, int a, int b) {
        int t = x[a];
        x[a] = x[b];
        x[b] = t;
        double d = n[a];
        n[a] = n[b];
        n[b] = d;
    }

    private static <T> void swap(List<T> lst, int[] n, int a, int b) {
        T c = lst.get(a);
        lst.set(a, lst.get(b));
        lst.set(b, c);
        int tn = n[a];
        n[a] = n[b];
        n[b] = tn;
    }

    private static void swap(int i, int j, int[]... arrays) {
        if (i != j) {
            final int arrCount = arrays.length;
            for (int a = 0; a < arrCount; a++) {
                int[] array = arrays[a];
                array[i] ^= array[j];
                array[j] ^= array[i];
                array[i] ^= array[j];
            }
        }
    }

    private static <T> void vecSwap(T[] arr, int offset1, int offset2,
            int len) {
        for (int i = 0; i < len; i++, offset1++, offset2++) {
            swap(arr, offset1, offset2);
        }
    }

    private static void vecSwap(int offset1, int offset2, int len,
            int[]... arrays) {
        final int numArrays = arrays.length;
        for (int i = 0; i < len; i++, offset1++, offset2++) {
            for (int j = 0; j < numArrays; j++) {
                swap(arrays[j], offset1, offset2);
            }
        }
    }

    /**
     * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
     */
    private static void vecswap(int x[], int a, int b, int n) {
        for (int i = 0; i < n; i++, a++, b++)
            swap(x, a, b);
    }
}

Related Tutorials