快速排序是效率較高的排序方法,採用了分治法。將一個大的數組分解成多個小數組,保證每一個小數組是順序的,則整個大數組也就是順序的了。
我學習的過程是這樣的:
1 先看了下維基百科上面的解釋。
2 自己分析整個過程。
3 寫代碼實現。
維基百科的解釋如下:
- 從數列中挑出一個元素,稱爲 "基準"(pivot),
- 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱爲分區(partition)操作。
- 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。
有了如上的解釋,我們自己分析下這個過程。
首先是有一個數組。然後我們隨便選取一個數字作爲基準,將所有小於該數字的元素,移動到左側。所有大於該數字的元素,移動到該數字的右側。我們這裏有個方法,就是基準元素,總是選擇這個數組序列的第一個元素。這樣的話,我們只用將小於該數字的元素移動到左側來即可。然後以這個基準元素的下標爲基準點,將該數組分成兩段,然後針對這兩個數組,確定其基準,再次排序。一直到所有的元素都確定順序後,整個排序過程結束。
看看整段代碼的結構。
package com.bplead.sort;
public class QuickSort {
public static void qsort(int a[],int begin,int end){
if(begin > end){
return;
}
prt(a);
int pivotindex = partition(a,begin,end);
qsort(a,begin,pivotindex-1);
qsort(a,pivotindex+1,end);
}
public static int partition(int a[],int left,int right){
int keyindex = left;
int temp = 0;
for(int i=left+1;i<=right;i++){
if(a[i] < a[keyindex]){
temp = a[i];
for(int j=i;j>keyindex;j--){
a[j] = a[j-1];
}
a[keyindex] = temp;
keyindex ++;
}
}
return keyindex;
}
public static void main(String[] args) {
int array[] = {43,24,12,56,78,9,67,50,1,2,1,9,87};
qsort(array,0,array.length-1);
}
private static void prt(int[] array){
for(int i=0;i<array.length;i++)
System.out.print(array[i] + " ");
System.out.println();
}
}
其實,整個快速排序的難點就在於基準元素位置的確定了。一旦確定了基準元素的位置,然後以此位置爲分割點,將數組分爲2個,遞歸進行處理即可。
我們看一下partition分區函數把。
我們將基準元素選擇爲第一個元素,循環遍歷整個數組,使其元素和基準元素進行比較,如果遍歷的當前元素比基準元素小,則當前元素以前的所有元素(不包含當前元素)都向右移動一位,當前元素放置到基準元素以前。一個分區函數執行完成後,所有小於該基準元素的元素都會移動到基準元素左側了。
我這裏把整個快速排序的過程都打印出來了,過程如下:
43 24 12 56 78 9 67 50 1 2 1 9 87
24 12 9 1 2 1 9 43 56 78 67 50 87
12 9 1 2 1 9 24 43 56 78 67 50 87
9 1 2 1 9 12 24 43 56 78 67 50 87
1 2 1 9 9 12 24 43 56 78 67 50 87
1 2 1 9 9 12 24 43 56 78 67 50 87
1 1 2 9 9 12 24 43 56 78 67 50 87
1 1 2 9 9 12 24 43 56 78 67 50 87
1 1 2 9 9 12 24 43 56 78 67 50 87
1 1 2 9 9 12 24 43 50 56 78 67 87
1 1 2 9 9 12 24 43 50 56 78 67 87
1 1 2 9 9 12 24 43 50 56 67 78 87
1 1 2 9 9 12 24 43 50 56 67 78 87
原數組是:
43 24 12 56 78 9 67 50 1 2 1 9 87
第一次分區操作:我們選擇43爲基準,則所有小於43的元素均在43左側。得到如下序列。
24 12 9 1 2 1 9 43 56 78 67 50 87
第二次分區操作,將43以前的元素當作一個序列,以後的元素也當作一個序列。我們需要注意的是,已經確定過的這個基準元素,作爲分割數組的標記,該元素不用劃分到左右兩個數組中。