很多时候排序是为了对数据进行归类,比如对城市进行排序,对员工的职业进行排序。这种排序的特点就是重复的值特别多。
如果使用普通的快排对这些数据进行排序,会造成N^2复杂度,但是归并排序和三路快排就没有这样的问题。
三路快排
三路快排的基本思想就是,在对数据进行分区的时候分成左中右三个部分,中间都是相同的值,左侧小于中间,右侧大于中间。
性能
三路快排的复杂度比普通快排小,主要取决于数据中重复数据的数量。重复数据越多,三路快排的复杂度就越接近于N。
代码
public class Quick3 { public static void sort(Comparable[] a) { Shuffle.shuffle(a); sort(a, 0, a.length); } public static void sort(Comparable[] a, int lo, int hi) { // 如果数组长度为0,直接返回 if(lo >= hi) { return; } // 将第一个元素作为分区依据 Comparable mid = a[lo]; // 对数组进行扫描,分区 int lt = lo; int gt = hi-1; int i = lo; while(true) { // 指针发生了交叉,退出循环 if(i > gt) { // 注意,这里不是i >= gt,i=gt的时候仍然需要排序 break; } int cmp = a[i].compareTo(mid); // 注意,这里不要用SortUtil.less if(cmp < 0) { SortUtil.exch(a,lt,i); lt++; i++; } else if(cmp > 0) { SortUtil.exch(a,gt,i); gt--; } else { // 跳过等值的情况。这就是为什么三路快排适合排序等值多的数组 i++; } } // 迭代排序 sort(a,lo,lt); sort(a,gt+1,hi); } }
普林斯顿公开课 算法3-3:三路快排
时间: 2024-10-15 20:08:48