快速排序应该是应用最广泛的排序算法,因为其实现简单,可以原地排序(只需要一个很小的辅助栈),且实现长度为N的数组排序只需要的时间和NlgN成正比。
思想
快排的思想其实就是给基准元素找其合适的位置的过程。(类似于给一个基准元素找位置的游戏)
我们先随意的在数组中找一个基准元素(可以是a[0]),然后从左侧开始扫描直到找到一个大于这个基准元素的元素时暂停,再从数组的最右侧扫描,直到找到一个小于这个基准元素的元素时为止,这是交换两个找到的元素。然后重复上述步骤进行扫描替换,直到两个扫描指针相遇,这时我们交换基准元素和左侧数组最右侧的元素。
比如现在我们有数组4,2,4,1,5,2。
1.我们选取第一个元素为基准元素即4,这时左右扫描指针(lo和hi)分别在如下的位置:
2.扫描左侧数组,当左侧元素小于等于基准元素4时lo指针加1。直到找到大于4的元素停下,这时指针位置如下:
3.扫描右侧数组,当右侧元素大于等于基准元素4时lo指针加1。直到找到小于4的元素停下,这时指针位置如下:
4.交换lo和hi处元素的位置,交换完后如下所示:
5.再次重复2,3,4步骤,直到lo>=hi指针,如下所示:
这时扫描完成。
6.此时基准元素和hi所处位置的元素交换,如下图所示:
此时基准元素就到了它该在的位置,因为此时它的左侧都不大与它,它的右侧都不小于它。
7.将基准元素的左侧和右侧分别按上面的1,2,3,4,5,6排序即可(这里用的是分治的思想):
算法实现
public class Merge {
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer[] a = new Integer[]{1,4,6,2,0,3,2,7,8,1,9};
sort(a);
SortUtil.show(a);
}
public static void sort(Comparable[] a){
sort(a,0,a.length-1);
}
public static void sort(Comparable[] a,int lo,int hi){
if (hi <= lo) {
return;
}
int j = partition(a, lo, hi);
sort(a,lo,j-1);
sort(a,j+1,hi);
}
//切分
private static int partition(Comparable[] a,int lo,int hi){
int i = lo;
int j = hi+1;
Comparable v = a[lo];
while(true){
while(SortUtil.less(a[++i], v)){
if (i == hi) {
break;
}
}
while(SortUtil.less(v, a[--j])){
if (i == lo) {
break;
}
}
if (i >= j) {
break;
}
SortUtil.exch(a, i, j);
}
SortUtil.exch(a, lo, j);
return j;
}
}