/***
*
* @author xiaoo_gan
* 三向切分的快速排序
* 适应场景:
* 出现含有大量重复元素的数组
* 实现思想:
* 将数组切分为三部分,分别对应小于、等于和大于切分元素的数组元素
* 特点:
* 三向切分的快速排序的运行时间和输入的信息量的N倍是成正比的
* 因为对于包含大量的重复元素的数组,它将排序时间从线性对数级降低到了线性级别
*
*/
public class Quick3Way {
public static void sort(Comparable[] a) {
StdRandom.shuffle(a); //消除对输入的依赖
sort(a, 0, a.length -1); //对a[0...length-1]排序
}
private static void sort(Comparable[] a, int lo, int hi) {
if(hi <= lo)
return;
int lt = lo; //维护lt指针,使得a[lo...lt-1]都小于value
int i = lo + 1; //维护i指针,使得a[lt...i-1]都等于value, a[i...gt]中的元素还未确定
int gt = hi; //维护gt指针,使得a[gt+1...hi]都大于value
Comparable value = a[lo]; //选择最左边的元素为切分元素
//不断缩小gt-i的值,即使得未确定的元素变少
while(i <= gt) { //还存在未确定的元素时
int cmp = a[i].compareTo(value);
if (cmp < 0) { // a[i] < value时,交换a[lt]和a[i],然后lt和i指针右移
exch(a, lt++, i++);
} else if (cmp > 0) { // a[i] > value时,交换a[i]和a[gt],然后gt指针左移,
// i指针不移动,因为无法判断交换后的a[i]的大小
exch(a, i, gt--);
} else { // a[i] = value时,直接右移指针i
i ++;
}
} // 现在a[lo...lt-1] < value = a[lt...gt] < a[gt+1..hi]成立
sort(a, lo, lt - 1); //对左半部分a[lo...j-1]排序
sort(a, gt + 1, hi); //对右半部分a[j+1...hi]排序
}
private static boolean less(Comparable a, Comparable b) {
return (a.compareTo(b) < 0);
}
private static void exch(Comparable[] a, int i, int j) {
Comparable swap = a[i];
a[i] = a[j];
a[j] = swap;
}
public static boolean isSorted(Comparable[] a) {
for (int i = 0; i < a.length - 1; i++) {
if(!less(a[i], a[i+1]))
return false;
}
return true;
}
private static void print(Boolean isSorted, Comparable[] a) {
if (isSorted) {
StdOut.println("after sorting :");
} else {
StdOut.println("before sorting :");
}
for (int i = 0; i < a.length; i++) {
if ((i % 10) == 0) {
if(i != 0)
StdOut.println();
StdOut.print("\t");
}
StdOut.print("\t" + a[i]);
}
StdOut.println();
}
public static void main(String[] args) {
int M = 200;
Double[] a = new Double[M];
for (int i = 0; i < M; i++) {
a[i] = StdRandom.uniform();
}
//String[] a = {"S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"};
//print(false, a);
Stopwatch timer = new Stopwatch();
sort(a);
double elapsedTime = timer.elapsedTime();
//print(true, a);
if(isSorted(a))
System.out.printf("排序 %d 个数, 快速排序用时: %.5f 秒", a.length, elapsedTime);
}
}
[算法之排序]三向切分的快速排序算法(java实现)
最新推荐文章于 2021-04-14 11:45:53 发布