快速排序是基於「分治法」原理實現,所謂分治法就是不斷的將原數組序列按照必定規律進行拆分,拆分後各自實現排序直到拆分到序列只剩下一個關鍵字爲止。快速排序首先選取一個關鍵字爲標誌位(關鍵字的選取影響排序效率),而後將序列中小於標誌位的關鍵字移動至標誌位左側,大於標誌位的關鍵字移動至右側。一趟比較完成後,整個序列以選取的標誌位爲界,左側均小於標誌位,右側均大於關鍵字。但左右兩側內部並非有序的(左右兩側關鍵字個數也不必定相同)。進而繼續將左右兩側分別再以這種方式進行排序,直到將序列拆分的剩餘一個關鍵字爲止,整個序列即變成有序。算法
下面以[6 ,1 ,2 ,7, 9 ,3 ,4 ,5 ,10 ,8]序列爲例用圖解的方式講解快速排序的過程數組
這裏咱們選取標誌位的方式是:序列左邊第一個關鍵字即 6 並放入標誌位變量flag中 ,而後將L(left)指針指向最左邊,將R(right)指針指向最右邊。dom
而後從右邊指針開始讓R指針指向的關鍵字與標誌位flag比較,若是關鍵字大於或等於flag,則繼續向左移動(右側關鍵字自己就要大於flag),直到找到小於flag的關鍵字,即關鍵字5。R指針中止移動。並開始讓L指針指向的關鍵字與flag比較,若是小於flag則L指針繼續向後移動,直到找到大於flag的關鍵字,即關鍵字7。此時序列以下圖所示 測試
此時再比較指針L是否小於R,知足條件,交換兩指針對應的值,即7與5交換。交換後仍知足L<R指針,繼續從R指針與flag比較,找小於6的關鍵字,即指向關鍵字4,R指針中止移動。並開始讓L指針指向的關鍵字與flag比較,找大於6的關鍵字,即指向關鍵字9。此時序列以下圖所示ui
此時仍知足L<R的條件,因此將9與4交換。繼續按照上述步驟進行,R向前移動並找到小於flag的關鍵字3,R指針中止移動。並開始L指針向後移動,當L指針指向3時,雖然知足3<6,但此時再也不知足L<R(此時L=R)。而後將L和R同時指向的關鍵字3移動至序列左邊第一個關鍵字中,並將flag放入L和R指向的位置,這一趟比較結束。此時序列以下圖所示 spa
從圖中能夠看到,一趟比較後,整個序列以咱們選取的標誌位爲界,將整個序列分爲兩個部分,其中左邊部分關鍵字都小於標誌位,而右側部分均大於標誌位。但左右兩側內部無序。指針
而後再將左右兩側子序列分別執行上述步驟,直至左右兩側剩餘一個元素沒法再拆分時,整個序列即爲有序。 code
1 public static void quickSort(int[] array ,int left,int right){ 2 int l,r,flag,temp; 3 if(left >= right){ 4 return; 5 } 6 l = left; 7 r = right; 8 flag = array[left]; 9 while (l < r){ 10 //先從右邊找 11 while (array[r] >= flag && l < r){ 12 r --; 13 } 14 //再從左邊找 15 while (array[l] <= flag && l < r){ 16 l ++; 17 } 18 //交換 19 if(l < r){ 20 temp = array[l]; 21 array[l] = array[r]; 22 array[r] = temp; 23 } 24 } 25 //一趟交換完將基準值放入臨界位置 26 array[left] = array[l]; 27 array[l] = flag; 28 //向左遞歸 29 quickSort(array,left,l-1); 30 quickSort(array,l+1,right); 31 }
代碼分析blog
1)選取數組左邊第一個關鍵字爲標誌位,並暫存至flag中(注:標誌位選取的方式可用不一樣方式)排序
2)第一層while循環用於保證一趟比較遍歷完全部關鍵字
3)第二層第一個while循環用於從右側依次向左找小於flag的關鍵字
4)第二層第二個while循環用於從左側依次向右找大於flag的關鍵字
5)第二層的兩個while循環執行後,若是l<r則進行交換
6)一趟比較後,將l和r共同指向的關鍵字放入最左側,即flag的選取位置,並將flag值放入此位置,此時序列便以flag爲界,左邊均小於flag,右邊均大於flag
7)而後再用「分治法」分別向左和向右遞歸執行上述步驟,直到沒法拆分爲止,整個序列即爲有序
快速排序時間複雜度爲O(NlogN)
與前面的排序算法相同,咱們依然生成10萬個隨機數的數組,使用插入排序方法進行排序,看其執行時間。測試代碼以下
public static void main(String[] args){ int array[] = new int[100000]; for (int i = 0; i < 100000; i++) { array[i] = (int) (Math.random()*1000000); } long begin = System.currentTimeMillis(); quickSort(array,0,array.length-1); System.out.println("總耗時="+(System.currentTimeMillis()-begin)+"毫秒"); }
能夠看到快速排序對10萬個關鍵字的數組進行排序,只用了50多毫秒,相比咱們前面講解的希爾排序又快了許多。
快速排序每趟比較首先選取某個關鍵字做爲標誌位,而後使用左右指針遍歷數組關鍵字與flag進行比較,並將右側小於flag的關鍵字與左側大於flag的關鍵字進行交換。而後再使用「分治法」方式對數組拆分,將數組以flag爲界拆分爲左右兩個子序列,並對兩個子序列遞歸執行上述步驟,直到子序列剩餘1個關鍵字沒法拆分爲止,此時整個序列即爲有序。