原理:
從數組中選取一個元素作爲基準(通常取第一個元素),然後將小於等於該元素的值移動到該元素的左邊,大於該元素的值移到該元素的右邊,然後循環對左右兩邊的元素進行相同的操作,直到每個分組的元素個數都爲1。
要點:
如何將小於等於基準數的元素移到基準的左邊,如何將大於基準數的元素移到基準的右邊,如何控制循環的結束。
講解:
設數組爲array[0...n-1].
1. 初始時基準數pivot=array[0],i = 0,j = n-1,tmp = pivot ;從 i = 0 ...n-1 開始查找大於pivot 的元素,從 j = n-1...0 開始查找小於等於 pivot 的元素;
2. 從j開始往前查找小於等於 pivot 的元素,將array[j]與pivot 相比較,如果array[j] <= pivot,則array[i] = array[j],i++ ;否則j-- ,直到array[j] <= pivot 或者 j == i 時結束一趟快速排序。
3. 從i開始往後查找大於 pivot 的元素,將array[i] 與 pivot 相比較,如果array[i] > pivot,則array[j] = array[i],j-- ;否則 i++,直到 array[i] > pivot 或者 i == j時結束結束一趟快速排序。
4. 經過第2、3步將數組分成了兩組,小於等於 pivot 的元素在pivot 的左邊,大於 pivot 的元素在pivot 的右邊,繼續循環2、3分別對左右兩邊的元素進行快速排序,直到每個小組元素都爲1時結束整個快速排序過程。
實例:
現有數組[6,2,4,1,9,5],要求對其進行升序排序。
1. 初始時(圖1.1):基準pivot = array[0] = 6 ,i = 0,j = 5,tmp = pivot ;(此時可以想象array[0]空出了位置,等於小於pivot的元素插入);
2. 對元素array[j]與pivot進行比較:array[5] < 6,故array[i] = array[j],即array[i=0] = 5,i++ ;(此時可以想象array[j=5]空出了位置,等待大於pivot的元素插入);
3. 對元素array[i] 與pivot進行比較:array[1] < 6,不進行賦值,i++ ;
4. 對元素array[i] 與 pivot進行比較:array[2] < 6,不進行賦值,i++ ;
5. 對元素array[i] 與pivot進行比較:array[3] < 6,不進行賦值,i++ ;
6. 對元素array[i] 與pivot進行比較:array[4] > 6,array[j=5] = array[i=4] = 9,j-- ;(此時可以想象array[i=4]空出了位置,等待小於等於pivot的元素插入);
7.此時 i == j == 4 ,將元素基準6插入到空出的位置中,即array[4] = 6 ;
8.至此,完成了第一趟快速排序,排序後的結果爲:[5,2,4,1,6,9] ;
9. 以 i = 4爲分界,繼續對左右兩邊的元素進行快速排序,即對[5,2,4,1]和[9]進行快速排序,由於[9]只有一個元素,所以不需要進行排序,以下對[5,2,4,1]循環①至⑧的過程進行快速排序;
10. 基準 pivot = array[0] = 5,i = 0,j = 3,tmp = pivot ;(此時可以想象array[0]空出了位置,等待等於小於pivot的元素插入);
11. 對元素 array[j]與pivot進行比較:array[3] < 5,故 array[i] = array[j],即array[0] = 1,i++ ;(此時可以想象array[j=3]空出了位置,等待大於pivot的元素的插入);
12. 對元素 array[i] 與 pivot 進行比較:array[1] < 5, 不進行賦值,i++ ;
13. 對元素 array[i] 與pivot 進行比較:array[2] < 5,不進行賦值,i++ ;
14. 此時 i == j == 3,將元素基準5插入到空出的位置中,即array[3] = 5;
15. 至此,完成了第二趟快速排序,排序後的結果爲:[1,2,4,5,6,9] ;
16. 同理,以 i = 3 位分界,繼續對左右兩邊的元素進行快速排序,最終排序後的結果:[1,2,4,5,6,9]
程序:
/**
* 快速排序法
*
* @param array
* 待排序的分組
* @param left
* 分組起始索引
* @param right
* 分組終止索引
*/
private static void quickSort(int[] array, int left, int right) {
if (left < right) {
int pivot = array[left];
int low = left;
int high = right;
while (low < high) {
//將小於等於pivot的元素移動到pivot左邊
while (low < high && array[high] >= pivot) {
high--;
}
array[low] = array[high];
//將大於pivot的元素移動到pivot右邊
while (low < high && array[low] < pivot) {
low++;
}
array[high] = array[low];
}
array[low] = pivot;
quickSort(array, left, low - 1);
quickSort(array, low + 1, right);
}
}
/**
* 快速排序法2
* @param array 待排序的分組
* @param left 分組起始索引
* @param right 分組終止索引
*/
public static void quickSort2(int[] array, int left, int right) {
if (left < right) {
int pivot = array[left];
int low = left;
int high = right;
while (low < high) {
while (low < high && array[high] >= pivot) {
high--;
}
array[low] = array[high];
if (low < high) { // 如果low = high,此時low不應該再++
low++;
}
while (low < high && array[low] < pivot) {// 從左向右找第一個大於等於x的數
low++;
}
array[high] = array[low];
high--;
}
array[low] = pivot;
quickSort2(array, left, low - 1);
quickSort2(array, low + 1, right);
}
}