1. 程式人生 > >java——快速排序

java——快速排序

快速排序

快速排序就是分割交換的排序方法,是目前公認的最佳排序方法,在最快以及平均情況下,時間複雜度為O(nlogn)。最壞情況(資料本身就有序)就是每次挑中的基準值不是最大就是最小,其時間複雜度為O(n^2);不穩定,在最差情況下的空間複雜度為O(n),而最佳情況下為O(nlogn)。快速排序法是平均執行時間最快的排序法。

快速排序的思想:它的原理和氣泡排序一樣,都是用交換的方式,不過它會現在資料中找一個基準,把小於這個基準的資料放在左邊,大於基準的放在右邊。再以同樣的方式處理兩邊的資料。

現定義兩個下標,low和high分別指向第一個和最後一個,low從前往後走,high從後往前走,一般第一次以第一個元素為基準:

這裡寫圖片描述

把小於這個基準的資料放在左邊,大於基準的放在右邊:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

比較完一趟,確定了選的基準的有序位置,且基準左邊的都比基準小,右邊的都比基準大;然後在再這個有序元素進行兩邊同樣的比較,直至所有的元素位置都確定了就排序完了。

動態示意圖:
這裡寫圖片描述

1、遞迴法

/**
 * @ClassName TestDemo1
 * @Description 快速排序
 * @Author lzq
 * @Date 2018/10/27 21:24
 * @Version 1.0
 **/
public class TestDemo1 {
    public static void main(String[] args) {
        int[] array = {20,1,9,56,25,32,87,45,12,69,54,19};
        System.out.println(Arrays.toString(array));
        quickSort(array);
        System.out.println(Arrays.toString(array));

    }

    /**
     * 快速排序
     * @param array
     */
    public static void quickSort(int[] array) {
        sort(array,0,array.length-1);
    }

    /**
     * 遞迴的排序資料
     * @param array
     * @param start
     * @param end
     */
    private static void sort(int[] array,int start,int end) {
        int once = once(array,start,end);
        if(once > start) {  //排序左邊
            sort(array,start,once-1);
        }
        if(once < end) {  //排序右邊
            sort(array,once+1,end);
        }
    }

    /**
     * 一趟快速排序
     * @param array
     * @param start
     * @param end
     * @return
     */
    private static int once(int[] array,int start,int end) {
        int tmp = array[start];
        while(start < end) {
            while(start < end && array[end] >= tmp) {
                --end;
            }
            array[start] =  array[end];  //把比基準tmp大的數字移到後面

            while(start < end && array[start] <= tmp) {
                ++start;
            }
            array[end] = array[start];  //把比基準tmp小的數字移到前面
        }
        array[start] = tmp;   //把基準放在它該放的位置
        return start;        //返回基準的位置,後面分別在這個基準位置兩邊重複上面的操作
    }
}

執行結果:

[20, 1, 9, 56, 25, 32, 87, 45, 12, 69, 54, 19]
[1, 9, 12, 19, 20, 25, 32, 45, 54, 56, 69, 87]

2、非遞迴法

就是用棧的方式去實現:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

不停的出棧入棧到最後把棧出空即可:

/**
 * @ClassName TestDemo2
 * @Description 非遞迴實現快速排序
 * @Author lzq
 * @Date 2018/10/27 21:49
 * @Version 1.0
 **/
public class TestDemo2 {
    public static void main(String[] args) {
        int[] array = {20,23,98,54,12,15,19,3,46,78,59,84};
        System.out.println(Arrays.toString(array));
        quickSort(array,0,array.length-1);
        System.out.println(Arrays.toString(array));

    }


    /**
     * 利用棧非遞迴的排序資料
     * @param array
     * @param start
     * @param end
     */
    private static void quickSort(int[] array,int start,int end) {
        int[] stack = new int[array.length];  //一個數組實現的棧
        int top = 0;
        int low = 0;
        int high = array.length-1;
        int once = once(array,low,high);

        //入棧
        if(once > low+1) { //用以排序左邊
            stack[top++] = low;
            stack[top++] = once-1;
        }
        if(once < high-1) {  //用以排序右邊
            stack[top++] = once+1;
            stack[top++] = high;
        }

        //出棧
        while(top > 0) {
            high = stack[--top];
            low = stack[--top];
            once = once(array,low,high);

            if(once > low+1) {
                stack[top++] = low;
                stack[top++] = once-1;
            }
            if(once < high-1) {
                stack[top++] = once+1;
                stack[top++] = high;
            }
        }
    }

    /**
     * 一趟快速排序
     * @param array
     * @param start
     * @param end
     * @return
     */
    private static int once(int[] array,int start,int end) {
        int tmp = array[start];
        while(start < end) {
            while(start < end && array[end] >= tmp) {
                --end;
            }
            array[start] =  array[end];  //把比基準tmp大的數字移到後面

            while(start < end && array[start] <= tmp) {
                ++start;
            }
            array[end] = array[start];  //把比基準tmp小的數字移到前面
        }
        array[start] = tmp;   //把基準放在它該放的位置
        return start;        //返回基準的位置,後面分別在這個基準位置兩邊重複上面的操作
    }

}

執行結果:

[20, 23, 98, 54, 12, 15, 19, 3, 46, 78, 59, 84]
[3, 12, 15, 19, 20, 23, 46, 54, 59, 78, 84, 98]