1. 程式人生 > >八大基本排序---快速排序(經典快排、隨機快排)(荷蘭國旗問題)

八大基本排序---快速排序(經典快排、隨機快排)(荷蘭國旗問題)

code idt title ati temp tmp com 劃分 移動

引言:

技術分享圖片

解答:

技術分享圖片

需要準備3個下標

技術分享圖片

如果當前數字=num,cur跳下一個

技術分享圖片

如果數組中的當前數字<num,把這個數(3)和小於區域的下一個數(5)交換

技術分享圖片

然後小於區域擴一下

技術分享圖片

然後cur跳下一個位置

技術分享圖片

數組中的當前數字<num,把這個數(2)和小於區域的下一個數(5)交換,

然後小於區域擴一下

然後cur跳下一個位置

技術分享圖片

PS:

如果一上來遇到的就是cur<num

把這個數(3)和小於等於區域的下一個數(3)交換【自己和自己交換】

技術分享圖片

數組中的當前數字>num,把這個數(7)和大於區域的前一個數(x)交換

然後大於區域向左擴一個位置,more移動一下

然後讓cur停留在原地,繼續考察換過來的x跟num的大小關系

技術分享圖片

當cur == more的時候,整個過程停止

public class Code_08_NetherlandsFlag {

    public static int[] partition(int[] arr, int L, int R, int num) {
        int less = L - 1;
        int more = R + 1;
        while (L < more) {
            if (arr[L] < num) {
                swap(arr, ++less, L++);
            } 
else if (arr[L] > num) { swap(arr, --more, L); } else { L++; } } //less + 1:等於區域的第一個位置,more - 1:等於區域的最後 一個位置 return new int[] { less + 1, more - 1 }; } // for test public static void swap(int[] arr, int
i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } }

傳統快排:與荷蘭國旗問題類似

技術分享圖片

import java.util.Arrays;

//利用荷蘭國旗問題進行快排
public class QuickSort {

    public static void main(String[] args) {
        int[] arr = {3,1,4,5,2,2,0,13};
        System.out.println(Arrays.toString(arr));
//        int[] res = new int[2];
//        res = partition(arr, 0, arr.length-1);
//        System.out.println(res[0]+" " +res[1]);
//        System.out.println(Arrays.toString(arr));
        quickSort(arr, 0, arr.length-1);
        System.out.println(Arrays.toString(arr));
        
    }
    
    public static void quickSort(int[] arr,int L,int R){
        if (L>=R) {
            return;
        }
        int[] p = partition(arr, L, R);
        quickSort(arr, L, p[0]-1);
        quickSort(arr, p[1]+1, R);
    }
    
    //以數組的最後一個數字arr[R]作為num
    //返回等於區域的下標
    public static int[] partition(int[] arr,int L ,int R){
        int less = L-1;
        int more = R+1;
        int num = arr[R];
        while (L < more) {
            if (arr[L]==num) {
                L++;
            }else if (arr[L]<num) {
                swap(arr,++less,L++);
            }else if (arr[L]>num) {
                swap(arr,L ,--more );
            }
        }
        int[] res = {less+1,more-1};
        return  res;
    }
    
    public static void swap(int[] arr, int i, int j ){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

經典快排存在的問題:

如果是一個有序的數組,算法的時間復雜度是O(N^2)

如果所選的num剛好把數組平分為左:<num;右>num,算法的時間復雜度是O(N*logN)

技術分享圖片

一次只搞定了7這一個數字

下一次在<7的區間裏,只搞定了6,劃分為<6的區域和=6的區域

每一次都是一次O(N),所以總的是O(N^2)

或者

技術分享圖片

技術分享圖片

解決方法:隨機快排

隨機找到一個數,把這個數和最後一個數字交換,進行快排

技術分享圖片

技術分享圖片

這樣最差情況就是在某個概率的情況下出現的,此時時間復雜度就是一個概率事件

此時時間復雜度的長期期望:O(N*logN)

快排的額外空間復雜度:O(logN)

空間用在記錄劃分點

技術分享圖片

技術分享圖片

八大基本排序---快速排序(經典快排、隨機快排)(荷蘭國旗問題)