算法思想:
设两个指针i和j,它的初值分别为left和right。首先将基准记录r[left]移动至变量x中,使r[left]即r[i]相当于空单元,然后反复进行如下两个扫描过程,直至i和j相遇。
(1)j从右向左扫描,直到r[j]<x时,将人r[j]移至r[i],此时r[j]相当于空单元。
(2)i从左往右扫描,直到r[i]>x,将r[i]移至空单元r[j],此时r[i]相当于空单元。
当i和j相遇时,r[i](或r[j])相当于空单元,且r[i]的左边所记录的关键字均不大于基准记录的关键字,而r[i]右边所记录的关键字均不小于基准记录的关键字。
最后,将基准记录移至r[i]中,就完成了一次划分过程。
例子:举个栗子:对5,3,8,6,4这个无序序列进行快速排序,思路是右指针找比基准数小的,左指针找比基准数大的,交换之。
5,3,8,6,4 用5作为比较的基准,最终会把比5小的移动到5的左边,比5大的移动到5的右边。
5,3,8,6,4 首先设置i,j两个指针分别指向两端,j指针先扫描(思考一下为什么?)4比5小停止。然后i扫描,8比5大停止。交换i,j位置。
5,3,4,6,8 然后j指针再扫描,这时j扫描4时两指针相遇。停止。然后交换4和基准数。
4,3,5,6,8 一次划分后达到了左边比5小,右边比5大的目的。之后对左右子序列递归排序,最终得到有序序列。
上面留下来了一个问题为什么一定要j指针先动呢?首先这也不是绝对的,这取决于基准数的位置,因为在最后两个指针相遇的时候,要交换基准数到相遇的位置。一般选取第一个数作为基准数,那么就是在左边,所以最后相遇的数要和基准数交换,那么相遇的数一定要比基准数小。所以j指针先移动才能先找到比基准数小的数。
快速排序是不稳定的,其时间平均时间复杂度是O(nlgn)。
package com.haobi;
/*
* 快速排序
*/
public class QuickSort {
public static void sort(int[] array, int low, int high) {
int i,j;
int index;
if(low>=high) {
return;
}
i = low;//小指针
j = high;//大指针
index = array[i];//基准
while(i<j) {//直至i,j相遇,跳出循环
while(i<j&&array[j] >= index)//直至出现小于基准的数出现,跳出循环
j--;//大指针左移
if(i<j)
array[i++] = array[j];//将该数存入基准中,该数变为新的基准
while(i<j&&array[i]<index)//直至出现大于基准的数出现,跳出循环
i++;//小指针大移
if(i<j)
array[j--] = array[i];//将该数存入基准中,该数变为新的基准
}
array[i] = index;//i,j相遇,基准记录存入array[i]中
sort(array,low,i-1);//左边递归快排
sort(array,i+1,high);//右边递归快排
}
public static void quickSort(int[] array) {
sort(array,0,array.length-1);
}
public static void main(String[] args) {
int[] array = {45,53,18,36,72,30,48,93,15};
quickSort(array);
for(int i=0;i<array.length;i++) {
System.out.print(array[i]+" ");
}
}
}
程序输出结果如下:
15 18 30 36 45 48 53 72 93