一、原理

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后在按此方法对这两部分数据分别进行排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列的过程。

二、代码实现

package com.jdk8.SortTest;

public class QuickSort {

    public static void display(int[] arrays){
        for(int i = 0;i < arrays.length;i++){
            System.out.print(" " +  arrays[i] + " ");
        }
    }

    public static void main(String[] args){
        int[] arrays = {3,9,63,93,72,15,27,86};
        System.out.println("排序前的数据为:");
        display(arrays);
        doQuickSort(arrays,0,arrays.length-1);
        System.out.println();
        System.out.println("排序后的数据为:");
        display(arrays);
        System.out.println();

    }

    private static void doQuickSort(int[] arrays,int left,int right) {
        if(left >= right){
            return;
        }
        int index = partition(arrays,left,right);
        doQuickSort(arrays,left,index-1);
        doQuickSort(arrays,index+1,right);
    }

    private static int partition(int[] arrays, int left, int right) {
        int key = arrays[left];
        while(right > left){
            while(arrays[right] > key && right > left){
                right = right - 1;
            }
            if(left != right){
                arrays[left] = arrays[right];
            }
            while(arrays[left] <= key && left < right){
                left = left + 1;
            }
            if(left != right){
                arrays[right] = arrays[left];
            }
        }
        arrays[right] = key;
        return right;
    }

}

三、复杂度分析

3.1、时间复杂度分析

​ 快速排序时间复杂度为n*lg(n) ,推导过程如下所示:

f(n)来表示数据量为n时,算法的计算次数,很容易知道:
- 当n=1时,quick_sort函数只计算1次
f(1)=1【式子A】

在n很大时:
第一步,先做一次partition;
第二步,左半区递归;
第三步,右半区递归;
即:
f(n)=n+f(n/2)+f(n/2)=n+2*f(n/2)【式子B】
画外音:
(1)partition本质是一个for,计算次数是n;
(2)二分查找只需要递归一个半区,而快速排序左半区和右半区都要递归,这一点在*分治法与减治法*一章节已经详细讲述过;

【式子B】不断的展开,
f(n)=n+2*f(n/2)
f(n/2)=n/2+2*f(n/4)
f(n/4)=n/4+2*f(n/8)
…
f(n/2^(m-1))=n/2^(m-1)+2f(n/2^m)

上面共m个等式,逐步带入,于是得到

f(n)=n+2*f(n/2)
=n+2[n/2+2f(n/4)]=2n+4*f(n/4)
=2n+4[n/4+2f(n/8)]=3n+8f(n/8)
=…
=mn+2^mf(n/2^m)

再配合【式子A】:

f(1)=1
即,n/2^m=1时, f(n/2^m)=1, 此时m=lg(n), 这一步,这是分析这个算法的关键。
将m=lg(n)带入,得到:

f(n)=lg(n)n+2^(lg(n))f(1)=n*lg(n)+n

故,快速排序的时间复杂度是n*lg(n)。

3.2、空间复杂度

​ 快速排序的临时变量所占用的空间不随处理数据n的大小改变而改变,即空间复杂度为O(1)。

四、稳定性

​ 快速排序是一个不稳定的排序

​ 例如(5,3A,6,3B)对这个进行排序,排序之前相同的数3A与3B,A在B的前面,经过排序之后会变成

(3B,3A,5,6),所以说快速排序是一个不稳定的排序

posted on 2019-02-18 23:01  IT-飞鹰  阅读(127)  评论(0编辑  收藏  举报