基本思想:算法
一、選擇一個基準元素,一般選擇第一個元素或者最後一個元素。ide
二、經過一趟排序將待排序的記錄分割成獨立的倆部分,其中一部分記錄元素值均比基準元素值小,另外一部分記錄元素的值均大於基準元素值。性能
三、此時基準元素在其排好序後的正確位置。ui
四、而後分別對這倆部分記錄繼續用一樣的方法進行排序,知道整個序列有序。spa
快速排序的示例:code
(a)一趟排序的過程:blog
(b)排序的全過程:排序
算法的實現:遞歸
遞歸實現:it
public class QuickSort { public static void main(String[] args) { int[] a = { 12, 23, 34, 45, 54, 43, 32, 21 }; quickSort(a, 0, a.length - 1); for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } } public static void quickSort(int[] a, int low, int high) { if (low < high) { int privotLoc = partition(a, low, high);// 將表一分爲二 quickSort(a, low, privotLoc - 1);// 遞歸對低子表遞歸排序 quickSort(a, privotLoc + 1, high);// 遞歸對高子表遞歸排序 } } public static int partition(int[] a, int low, int high) { int privotkey = a[low]; // 基準元素 while (low < high) { // 從表的倆端,交替的向中間掃描 while (low < high && a[high] >= privotkey) { // 從high // 所指位置向前搜索,至多到low+1 // 位置。將比基準元素小的交換到低端 --high; } swap(a, low, high); while (low < high && a[low] <= privotkey) { ++low; } swap(a, low, high); } return low; } public static void swap(int a[], int low, int high) { int temp = a[low]; a[low] = a[high]; a[high] = temp; } }
分析:
快速排序是被認爲是同數量級(O(nlon2n))的排序方法中平均性能最好的。但若初始序列按關鍵碼有序或基本有序時,快速排序反而退化爲冒泡排序。爲改進之,一般以「三者取中法」來選取基準記錄,即將排序區間的倆個端點與中點三個記錄關鍵碼居中的調整爲支點記錄。快速排序就是一個不穩定的排序方法。
快速排序的改進:
在本改進方法中,只對長度大於k的子序列遞歸調用快速排序,,讓原序列基本有序,而後對整個基本有序的序列用插入排序算法排序。實踐證實,改進後的時間複雜度有所減低,且當k取值爲8左右時,改進算法的性能最佳。算法思想以下:
public class QuickSort2 { public static void main(String[] args) { int[] a = { 12, 23, 34, 45, 54, 43, 32, 21 ,23,65,89,32,19,2,3,921,980}; quickSort(a, 0, a.length - 1,4); for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } } public static void quickSort(int[] a, int low, int high, int k){ quickSortImporve(a, low, high, k); for(int i=1;i<a.length;i++){ int x = a[i]; int j = i-1; while(j>=0 && x<a[j]){ a[j+1] = a[j]; j--; } a[j+1] = x; } } public static void quickSortImporve(int[] a,int low,int high,int k){ if(high-low>k){ //長度大於k時遞歸,k爲指定的數 int pivotLoc = partition(a, low, high); quickSortImporve(a, low, pivotLoc-1, k); quickSortImporve(a, pivotLoc+1, high, k); } } public static int partition(int[] a, int low, int high){ int privotKey = a[low]; //基準元素 while(low<high){ //從表的倆端,交替的向中間掃描 while(low < high && a[high] >= privotKey) { --high; } swap(a,low,high); while(low < high && a[low] <= privotKey){ ++low; } swap(a,low,high); } return low; } public static void swap(int[] a, int low,int high){ int temp = a[low]; a[low] = a[high]; a[high] = temp; } }