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