三向切分的快速排序是对快速排序算法改进,特别适用于有大量重复元素的数组的排序,其时间复杂度介于N - NlogN之间,最好的时间复杂度接近于O(N),在没有重复元素的情况下有最坏的时间复杂度,空间复杂度为lgN。
三向切分的快速排序算法在包括重复元素很多的情况下,要比归并排序和其他排序方法有更好的性能。
三向切分的快速排序的过程是这样的:从左到右遍历数组一次,维护一个指针lt使得a[lo ... lt - 1]中的元素都小于v,一个指针gt使得a[gt + 1 ... hi]中的元素都大于v,一个指针使得a[lt...i - 1]中的元素都等于v,a[i ... gt]中的元素都还不确定,如下图所示:
一开始i = lo,使用Comparable接口对a[i]进行三向比较处理:
1)、a[i]小于v,将a[lt]和a[i]交换,然后将lt和i加一;
2)、a[i]大于v,将a[gt]和a[i]交换,然后将gt减一;
3)、a[i]等于v,然后将i加一;
除非和切分元素相等,其他元素都会被交换。全部代码如下:
/** * 三向切分的快速排序算法:有大量重复元素的快速排序 * @author jacky * */ public class Quick3waySort extends SortBase{ public static void sort(Comparable[] a){ //为获得接近于最好的排序性能(最好的时间复杂度),首先将原数组“洗牌" shuffle(a); //开始排序 sort(a,0,a.length - 1); } /** * 三向切分的快速排序实现 * @param a * @param lo * @param hi */ private static void sort(Comparable[] a,int lo,int hi){ if(hi <= lo) return; int lt = lo; int i = lo + 1; int gt = hi; Comparable v = a[lo]; int cmp = 0; while(i <= gt){ cmp = a[i].compareTo(v); if(cmp < 0){ exch(a,lt++,i++); }else if(cmp > 0){ exch(a,i,gt--); }else{ i++; } }//现在a[lo ... lt - 1] < v = a[lt ... gt] < a[gt + 1 ... hi]成立 sort(a,lo,lt - 1); sort(a,gt + 1,hi); } }