陣列排序-快速排序(Quick Sort)
概念:
快速排序是對氣泡排序的一種改進。由C.A.R.Hoare於1962年提出。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
排序過程:
假設要排序的陣列是A[0]..A[N-1],首先任意選取一個數據(通常選用陣列的第一個數)作為關鍵資料,然後將所有比它小的數都放到它的前面,所有比它大的資料都放到它的後面,這個過程稱為一趟快速排序。值得注意的是:快速排序不是一種穩定的排序演算法,也就是說,多個相同的值的相對位置也許會在演算法結束時產生變動。
一趟快速排序的演算法是:
1.設定兩個變數i、j,排序開始時:i=0; j=N-1;
2.以第一個陣列元素作為關鍵資料,賦值給key,即key=A[0];
3.從j開始向前檢索,即由後向前開始檢索(j--),找到第一個小於key的值A[j],將A[j]和A[i]互換;
4.從i開始向後檢索,即由前向後開始檢索(i++),找到第一個大於key的A[i],將A[i]和A[j]互換;
5.重複第3、4步,直到i=j;(3、4步中,沒找到符合條件的值,即第3步中A[j]不小於key,第4步中A[i]不大於key時改變i、j的值,使得j=j-1; i=i+1; 直至找到該值為止。找到符合條件的值,進行交換的時候i和j的指標位置不變。另外,i==j這一過程一定正好是i++或j--完成的時候,此時令迴圈結束)
示例:
package com.cnblogs.lxj.testarraysort; /** * @author liuxiaojiang * @packageName:com.cnblogs.lxj.testarraysort * @ClassName:QuickSort * @Description:測試快速排序 * @date 2020/11/30 */ public class QuickSort { /** * 主方法 * @param args */ public static void main(String[] args) { int[] a = {5,1,9,3,7,4,8,6,2}; printArray(a); quickSort(0,a.length - 1,a); printArray(a); } /** * 快速排序方法 * @param low * @param high * @param a */ public static void quickSort(int low,int high,int[] a){ if(low < high){ int middle = getMiddle(low,high,a); quickSort(low,middle - 1,a); quickSort(middle + 1,high,a); } } /** * 邏輯演算法 * @param low * @param high * @param a * @return */ public static int getMiddle(int low,int high,int[] a){ int temp = a[low]; while(low < high){ while(a[high] >= temp && low < high){ high--; } a[low] = a[high]; low++; while(a[low] <= temp && low < high){ low++; } a[high] = a[low]; } a[high] = temp; return high; } /** * 輸出方法 * @param array */ public static void printArray(int[] array){ for(int a : array){ System.out.print(a + " "); } System.out.println(); } }
執行結果:
5 1 9 3 7 4 8 6 2 //初始化
1 2 3 4 5 6 7 8 9 //快速排序完成
原理:
演算法分析:
快速排序可以說是陣列排序中效能最好的排序演算法,但它是不穩定的演算法,比如當同一陣列中有兩個(或多個)值相同的元素時,排序完成後,該多個元素位置(順序)可能會發生改變。快速排序主要有兩個基本操作:一是選取樞軸元素,另一個則是遞迴分割陣列。樞軸元素的選取對快速排序的效率至關重要,因為它決定了遞迴的深度。如果樞軸元素剛好處於陣列的中間值,那麼,陣列在分割時就分成了平均的兩部分。這樣的遞迴的效率就好。如果每次選取的樞軸元素都是最大/最小 的那個元素,則快排複雜度達到了O(N^2),而且還用了遞迴棧空間。快速排序的時間複雜度與樞軸元素的選取息息相關。平均情況下,時間複雜度為O(NlogN),最壞情況下為O(N^2)。所以,快速排序更適合資料量比較大時使用。(另:需要注意,當選取陣列元素中的最小值作為樞軸且要降序時,這時候的執行時間巨長,所以,在使用時需要根據實際情況調整)