快速排序以及使用快排找中位数

原创
2015/09/21 23:57
阅读数 5.6K

####快速排序


快速排序的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

我个人有个很风趣的理解方式:站住!!比我高的站右边!比我矮的站左边!递归中...

其实真正帮助我理解快速排序的还是在网上偶遇的一张动态图,但是现在已经找不到了。

以下纯属摘抄,时间复杂度的计算略显复杂:

快速排序的平均时间为 $T(n)=kn$ln$n$,其中n为待排序序列中记录的个数,k为某个常数,在所有同数量级(O($n$log$n$))的排序方法中,快速排序的常数因子k最小,就平均时间而言,快数排序的目前被认为是最好的一种内部排序方法

java实现

    public void quickSort(long[] array, int begin, int end){
        if (begin>=end)
            return;
        int b = begin;
        int e = end;
        long sentry = array[begin];
        while(begin<end){
            while (begin<end && array[end]>sentry) --end;
            array[begin] = array[end];
            while (begin<end && array[begin]<=sentry) ++begin;
            array[end] = array[begin];
        }
        array[begin] = sentry;

        quickSort(array, b, begin-1);
        quickSort(array, begin+1, e);
    }

突然有一天我想到可以使用快速排序可以查找中位数,当然,我所说的并不是让快速排序将一个数组排好序再去找中位数,而是向着中位数所在的位置去排序,例如有个数组[4,3,7,8,5,4,2,5,65],我们知道如果排序好之后,中位数就在下标为4的位置。选取第一个记录作为枢轴将这个数组快速排序一次,begin停留在2,这时按快速排序的思想,以这个枢轴所在位置的左右边再进行快速排序,但是此时对左边作快速排序是没有任何意义的,因为我们自己清楚,中位数最后会落到下标为4的位置,目标数肯定比枢轴数大,所以也比左边的数组中的所有数都大。所以算法如下(区分奇数和偶数)

    @Test
    public void _median_(){
        float[] medians = new float[]{1,2,3,4,5,6,7,8};
        if ((medians.length&0x01) == 0){
            median4even(medians, 0, medians.length-1);
        }else{
            median4odd(medians, 0, medians.length-1);
        }
    }

    /**
     * 奇数数组找中位数
     * @param array
     * @param low
     * @param high
     * @return
     */
    public float median4odd(float[] array, int low, int high){

        int pivot = xsort(array, low, high);

        if (low<array.length/2)
            return median4odd(array, pivot + 1, high);
        if (low>array.length/2)
            return median4odd(array, low, pivot - 1);
        else return array[pivot];
    }

    /**
     * 偶数数组去中位数
     * @param array
     * @param low
     * @param high
     * @return
     */
    public float median4even(float[] array, int low, int high){
        if (low>=high)
            return (array[array.length/2]+array[array.length/2-1])/2;

        int pivot = xsort(array, low, high);

        if (low<=array.length/2-1)
            return median4even(array, pivot + 1, high);
        else
            return median4even(array, low, pivot - 1);
    }

    /**
     * 给定数组范围快速排序一次
     * @param array
     * @param low
     * @param high
     * @return
     */
    public int xsort(float[] array, int low, int high){
        float sentry = array[low];
        while(low<high){
            while (low<high && array[high]>sentry) --high;
            array[low] = array[high];
            while (low<high && array[low]<=sentry) ++low;
            array[high] = array[low];
        }
        array[low] = sentry;
        return low;
    }
展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部