快速排序原理
時間複雜度: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);//二分
}
}