快速排序的原理及其實現(C++及Java版)淺析

快速排序原理

時間複雜度:O(nlog n),最壞情況下是n^2。值得一提的是對於所有基於比較的排序,其能取得的最好時間複雜度爲O(nlog n),可以從數學上證明它。而不基於比較的排序(如桶排序),可以突破這個極限。

快速排序是一種不穩定的排序算法。

基於二分的思想,先隨機選定一個基準數(比如最左邊的),然後從一個指針從最右邊找比基準數小的數,一個指針從最左邊找比基準數大的數,然後兩數交換位置,重複找並交換的過程,最終在兩個指正相碰時,該位置就是基準數在最終排好序時的結果,將基準數和該位置上的數交換位置,即可。然後根據基準數的位置二分,在兩邊依次使用快速排序。

終止條件:劃分到只有1或0個元素時即可終止。

爲什麼該位置是基準數在最終排好序時的位置

因爲此時,該位置的右邊都是小於或等於基準數的數,左邊都是大於或等於基準數的數。觀察如下排序前和排序後的數組:

4 2 4 5 3 1

1 2 4 3 4 5

對於已經排好序的數組中的每一個數,其左邊的數都小於等於它,右邊的數都大於等於它。

C++版

/*
快速排序
*/
#include <stdio.h>
using namespace std;
void swap(int &a, int &b){
  a ^= b;
  b ^= a;
  a ^= b;
} 
void quicksort(int *p, int left, int right){
  if(left >= right)return;
  int i = left, j = right, tmp = p[left];
  while(i < j){
    while(i < j && p[j] >= tmp)j--;
    while(i < j && p[i] <= tmp)i++;
    if(i != j){
      swap(p[i], p[j]);
    }
  }
  p[left] = p[i];
  p[i] = tmp;
  quicksort(p, left, i - 1);
  quicksort(p, i + 1, right);
}
void sort(int *p, int len){
  quicksort(p, 0, len - 1);
}
int main(){
  
}

Java版

import java.security.SecureRandom;
import java.util.Arrays;

class Scratch {
    public static void main(String[] args) {
        //測試代碼
        int[] array = new int[14];
        SecureRandom secureRandom = new SecureRandom();
        for (int i = 0; i < array.length; i++) {
            array[i] = secureRandom.nextInt(15);
        }
        int[] cArray = array.clone();

        System.out.println("before");
        System.out.println(Arrays.toString(array));
        QuickSort.quickSort(array, 0, array.length - 1);
        System.out.println("after");
        System.out.println(Arrays.toString(array));

        System.out.println();
        System.out.println("final");
        Arrays.sort(cArray);
        System.out.println(Arrays.toString(cArray));
    }
}

class QuickSort {
    public static void swap(int[] array, int posA, int posB) {
        int t = array[posA];
        array[posA] = array[posB];
        array[posB] = t;
    }

    public static void quickSort(int[] array, int left, int right) {
        if (left >= right) {//也可left > right,但是效率更低。當只有1個及以下時就不需要再排序了
            return;
        }

        int i = left;
        int j = right;
        int tmp = array[left];//基準數
        while (i < j) {
            while (i < j && array[j] >= tmp) j--;//找比基準數小的,即:略過大於等於基準數的數
            while (i < j && array[i] <= tmp) i++;//找比基準數大的,即:略過小於等於基準數的數
            if (i != j) {
                swap(array, i, j);
            }
        }//跳出這個循環時,i=j,此時i代表基準數在最終排序結果中的位置

        swap(array, left, i);//此時(小於i的位置的數都小於等於基準數,大於i的位置的數都大於等於基準數)

        quickSort(array, left, i - 1);//二分,由於基準數已經有序,所以根據基準數劃分成2半依次排序
        quickSort(array, i + 1, right);//二分
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章