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

原理:

从数组中选取一个元素作为基准(通常取第一个元素),然后将小于等于该元素的值移动到该元素的左边,大于该元素的值移到该元素的右边,然后循环对左右两边的元素进行相同的操作,直到每个分组的元素个数都为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);
	}
}


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