常用排序算法之快速排序算法

原理:

從數組中選取一個元素作爲基準(通常取第一個元素),然後將小於等於該元素的值移動到該元素的左邊,大於該元素的值移到該元素的右邊,然後循環對左右兩邊的元素進行相同的操作,直到每個分組的元素個數都爲1

要點:

如何將小於等於基準數的元素移到基準的左邊,如何將大於基準數的元素移到基準的右邊,如何控制循環的結束。

講解:

設數組爲array[0...n-1].

1. 初始時基準數pivot=array[0]i = 0j = n-1tmp = 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. 經過第23步將數組分成了兩組,小於等於 pivot 的元素在pivot 的左邊,大於 pivot 的元素在pivot 的右邊,繼續循環23分別對左右兩邊的元素進行快速排序,直到每個小組元素都爲1時結束整個快速排序過程。


實例:

現有數組[6,2,4,1,9,5],要求對其進行升序排序。

1. 初始時(圖1.1):基準pivot = array[0] = 6 i = 0j = 5tmp = pivot (此時可以想象array[0]空出了位置,等於小於pivot的元素插入)

2. 對元素array[j]pivot進行比較:array[5] < 6,故array[i] = array[j],即array[i=0] = 5i++ ;(此時可以想象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] > 6array[j=5] = array[i=4] = 9j-- ;(此時可以想象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] = 5i = 0j = 3tmp = pivot ;(此時可以想象array[0]空出了位置,等待等於小於pivot的元素插入);

11. 對元素 array[j]pivot進行比較:array[3] < 5,故 array[i] = array[j],即array[0] = 1i++ ;(此時可以想象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);
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章