快速排序

1.快排的基本思想就是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可以对这两部分的记录继续排序,来达到整个序列有序的目的。
2.快速排序算法的实现

/** * 快速排序 * @param arr:待排序数组 * @param low:数组的首元素下标 * @param high:数组的尾元素下表 */
    public static void QSort(int[] arr,int low,int high){
        int pivot;
        if (low < high) {
            //将数组一分为二,算出枢纽值pivot
            pivot = Partition(arr,low,high);
            //对低子表进行递归排序
            QSort(arr, low, pivot - 1);
            //对高子表进行递归排序
            QSort(arr, pivot + 1, high);
        }
    }

    /** * 快排的核心算法 * @param arr * @param low * @param high * @return */
    private static int Partition(int[] arr, int low, int high) {
        int pivotkey;
        //假设数组的第一个元素是枢纽记录
        pivotkey = arr[low];
        //从数组的两端交替向中间扫描
        while (low < high) {
            while(low < high && arr[high] >= pivotkey){
                high--;
            }
            //将比选定值小的记录交换到低端
            swap(arr,low,high);
            while(low < high && arr[low] <= pivotkey){
                low++;
            }
            //将比选定值大的记录交换到高端
            swap(arr, low, high);
        }
        //返回选定值的位置所在
        return low;
    }

    private static void swap(int[] arr, int low, int high) {
        int temp = arr[low];
        arr[low] = arr[high];
        arr[high] = temp;
    }

3.快速排序的时间复杂度分析
(1)快速排序的时间性能取决于快速排序递归的深度,可以用递归树的方式来描述递归算法的执行情况。
(2)在最好的情况下快速排序的时间复杂度是O(nlogn)
(3)在最坏的情况下快速排序的时间复杂度是O(n^2)
(4)平均的情况下,用数学归纳法可以证得快速排序的时间复杂度是O(nlogn)
4.快速排序由于关键字的比较和交换是跳跃进行的,因此快速排序是一种不稳定的排序。
5.关于快速排序的优化
(1)优化选取关键字
优化方法:对于数组的元素可以通过取样取中的做法来获得pivotkey是比较接近中间值的数字。比如:有九个数字,可以分三次取样,算出这三个样的中间数,然后再取这三个数的中间数为选定值pivotkey做关键字,这个也叫做九数取中。
(2)优化不必要的交换

/** * 快排的核心算法 * @param arr * @param low * @param high * @return */
    private static int Partition(int[] arr, int low, int high) {
        int pivotkey;
        //三数取中作为pivotkey的值
        //计算数组中间元素的下标
        int m = low + (high - low)/2;
        //交换左端和右端的数据,保证左端较小
        if(arr[low] > arr[high]){
            swap(arr,low,high);
        }
        //交换中间和右端的数据,保证中间较小
        if(arr[m] > arr[high]){
            swap(arr,high,m);
        }
        //交换左端和中间的数据,保证左端较小
        if(arr[m] > arr[low]){
            swap(arr,m,low);
        //用数组的第一个记录作为关键字
        pivotkey = arr[low];
        //将关键字备份到数组的第一个存储位置
        arr[0] = pivotkey;
        //从数组的两端交替向中间扫描
        while (low < high) {
            while(low < high && arr[high] >= pivotkey){
                high--;
            }
            //将比选定值小的记录交换到低端
            arr[low] = arr[high];
            while(low < high && arr[low] <= pivotkey){
                low++;
            }
            //将比选定值大的记录交换到高端
            arr[high] = arr[low];
        }
        //将关键字的值替换回到arr[low]
        arr[low] = arr[0];
        //返回选定值的位置所在
        return low;
    }

(3)优化小数组时的排序方案
(4)优化递归操作

你可能感兴趣的:(算法,快速排序)