Quick Sort

简单快速排序

选取数组第一个元素为临界值,然后将数组排序,小于临界值得都放在临界值左边,大于临界值的都放在临界值右边,然后递归知道数组完全有序.但是如果数组基本有序或者数组中重复元素较多的情况下,临界值的依然选择第一个就不是很恰当了,所以后续会有快排的优化

/**
 * 简单快速排序--对于基本有序的数组和重复元素较多的数组时间复杂度较高,存在不足需要改进
 */
public class QuickSort {
    private QuickSort() {
    }

    //通过分区,返回两个区的临界值
    private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
        T temp = arr[low];
        int j = low;
        for (int i = low + 1; i <= high; i++) {
            if (arr[i].compareTo(temp) < 0) {
                j++;
                swap(arr, i, j);
            }
        }
        swap(arr, low, j);
        return j;
    }

    //递归将数组分区
    private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
        if (low >= high) {
            return;
        }
        int partition = partition(arr, low, high);
        sort(arr, low, partition - 1);
        sort(arr, partition + 1, high);
    }

    public static <T extends Comparable<? super T>> void sort(T[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    //交换数组中的两个元素
    private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印数组元素
    public static <T extends Comparable<? super T>> void printArray(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] arr = {9, 5, 1, 3, 7, 2, 8, 4, 6, 10};
        sort(arr);
        printArray(arr);
    }
}  

快速排序优化

优化一:如果基本有序数组的第一个元素是临界值,那么临界值很可能是最小的元素,导致分区不均,时间复杂度相当于O(n^2),所以为了尽量消除数组基本有序的情况,在数组中随机选取一个元素,解决了数组基本有序排序效率低的情况,但是若数组中存在大量重复元素,效率低的情况仍未解决.

优化二:对于数组中元素基本有序时,可以更换为直接插入排序,提高排序效率

public class QuickSort {
    private QuickSort() {
    }

    //通过分区,返回两个区的临界值
    private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
        /*优化一:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
        swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
        T temp = arr[low];
        int j = low;
        for (int i = low + 1; i <= high; i++) {
            if (arr[i].compareTo(temp) < 0) {
                j++;
                swap(arr, i, j);
            }
        }
        swap(arr, low, j);
        return j;
    }

    //递归将数组分区
    private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
        /*优化二:对于基本有序的数组可以使用直接插入排序*/
        if (high - low <= 15) {
            insertionSort(arr, low, high);
            return;
        }
        int partition = partition(arr, low, high);
        sort(arr, low, partition - 1);
        sort(arr, partition + 1, high);
    }

    public static <T extends Comparable<? super T>> void sort(T[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    // 对arr[l...r]的区间使用InsertionSort排序
    public static void insertionSort(Comparable[] arr, int l, int r) {

        for (int i = l + 1; i <= r; i++) {
            Comparable temp = arr[i];
            int j = i;
            for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
                arr[j] = arr[j - 1];
            arr[j] = temp;
        }
    }

    //交换数组中的两个元素
    private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印数组元素
    public static <T extends Comparable<? super T>> void printArray(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] arr = {9, 5, 1, 3, 7, 2, 8, 4, 6, 10};
        sort(arr);
        printArray(arr);
    }
}  

 快速排序--优化2

从左向右找比临界值大的,从右向左找比临界值小的,然后将两者交换,这样对于大量相同的元素不用全部交换,解决了数组中存在大量元素的问题

public class QuickSort {
    private QuickSort() {
    }

    //通过分区,返回两个区的临界值
    private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
        /*优化:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
        swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
        T temp = arr[low];
        int i = low + 1;
        int j = high;
        while (true) {
            while (i <= high && arr[i].compareTo(temp) < 0) {
                i++;
            }
            while (j >= low + 1 && arr[j].compareTo(temp) > 0) {
                j--;
            }
            if (i > j) {
                break;
            }
            swap(arr,i,j);
            i++;
            j--;
        }
        swap(arr, low, j);
        return j;
    }

    //递归将数组分区
    private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
        /*对于基本有序的数组可以使用直接插入排序*/
        if (high - low <= 15) {
            insertionSort(arr, low, high);
            return;
        }
        int partition = partition(arr, low, high);
        sort(arr, low, partition - 1);
        sort(arr, partition + 1, high);
    }

    public static <T extends Comparable<? super T>> void sort(T[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    // 对arr[l...r]的区间使用InsertionSort排序
    public static void insertionSort(Comparable[] arr, int l, int r) {

        for (int i = l + 1; i <= r; i++) {
            Comparable temp = arr[i];
            int j = i;
            for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
                arr[j] = arr[j - 1];
            arr[j] = temp;
        }
    }

    //交换数组中的两个元素
    private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印数组元素
    public static <T extends Comparable<? super T>> void printArray(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] arr = {9, 5, 1, 3,7, 7, 2, 8, 4, 6, 10};
        sort(arr);
        printArray(arr);
    }
}

两路快排--不交换 

public class QuickSort {
    private QuickSort() {
    }

    //通过分区,返回两个区的临界值
    private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
        /*优化:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
        swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
        T temp = arr[low];
        int i = low + 1;
        int j = high;
        while (i < j) {
            while (i < j && temp.compareTo(arr[j]) < 0) {
                j--;
            }
            arr[i] = arr[j]; //j停在那里不动
            while (i < j && temp.compareTo(arr[j]) > 0) {
                i++;
            }
            arr[j] = arr[i];//i停在那里不动
        }
        arr[j] = temp;
        return j;
    }

    //递归将数组分区
    private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
        /*对于基本有序的数组可以使用直接插入排序*/
        if (high - low <= 15) {
            insertionSort(arr, low, high);
            return;
        }
        int partition = partition(arr, low, high);
        sort(arr, low, partition - 1);
        sort(arr, partition + 1, high);
    }

    public static <T extends Comparable<? super T>> void sort(T[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    // 对arr[l...r]的区间使用InsertionSort排序
    public static void insertionSort(Comparable[] arr, int l, int r) {

        for (int i = l + 1; i <= r; i++) {
            Comparable temp = arr[i];
            int j = i;
            for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
                arr[j] = arr[j - 1];
            arr[j] = temp;
        }
    }

    //交换数组中的两个元素
    private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印数组元素
    public static <T extends Comparable<? super T>> void printArray(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] arr = {9, 5, 1, 3, 7, 7, 2, 8, 4, 6, 10};
        sort(arr);
        printArray(arr);
    }
}  

三路快排

public class QuickSort {
    private QuickSort() {
    }

    private static <T extends Comparable<? super T>> int[] partition(T[] arr, int low, int high) {
        swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
        T temp = arr[low];
        int i = low;
        int j = high;
        int cur = i;
        while (cur <= j) {
            if (temp.compareTo(arr[cur]) == 0) {
                cur++;
            } else if (temp.compareTo(arr[cur]) > 0) {
                swap(arr, cur++, i++);
            } else {
                swap(arr, cur, j--);
            }
        }
        return new int[]{i - 1, j + 1};
    }

    private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
        if (high - low <= 15) {
            insertionSort(arr, low, high);
            return;
        }

        int[] ret = partition(arr, low, high);
        sort(arr, low, ret[0]);
        sort(arr, ret[1], high);
    }

    public static <T extends Comparable<? super T>> void sort(T[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    // 对arr[l...r]的区间使用InsertionSort排序
    private static void insertionSort(Comparable[] arr, int l, int r) {

        for (int i = l + 1; i <= r; i++) {
            Comparable temp = arr[i];
            int j = i;
            for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
                arr[j] = arr[j - 1];
            arr[j] = temp;
        }
    }

    //交换数组中的两个元素
    private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印数组元素
    public static <T extends Comparable<? super T>> void printArray(T[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Integer[] arr = {9, 5, 1, 3, 7, 7, 2, 8, 4, 6, 10};
        sort(arr);
        printArray(arr);
    }
}

  

原文地址:https://www.cnblogs.com/Hangtutu/p/8023536.html