大学学的快速排序,现在已经忘了,重新学一遍.
最近学习了一篇快速排序的文章:
http://www.importnew.com/8445.html#comment-13445
发现里面双基准排序有点问题.修正如下:
package test;
import java.util.Arrays;
public class QuickSortDualPivot extends QuickSort {
public static void main(String[] args) {
int[] arr = new int[] { 3, 4, 2, 1, 3 };
QuickSortDualPivot test = new QuickSortDualPivot();
System.out.println(Arrays.toString(arr));
test.sort(arr);
System.out.println(Arrays.toString(arr));
}
public void sort(int[] input) {
sort(input, 0, input.length - 1);
}
private void sort(int[] input, int lowIndex, int highIndex) {
if (highIndex <= lowIndex)
return;
int pivot1 = input[lowIndex];
int pivot2 = input[highIndex];
if (pivot1 == pivot2) {
int temI = lowIndex;
while (pivot1 == pivot2 && temI < highIndex) {
temI++;
pivot1 = input[temI];
}
exchange(input, lowIndex, temI);
}
if (pivot1 > pivot2) {
exchange(input, lowIndex, highIndex);
pivot1 = input[lowIndex];
pivot2 = input[highIndex];
}
int i = lowIndex + 1;
int lt = lowIndex + 1;
int gt = highIndex - 1;
while (i <= gt) {
if (less(input[i], pivot1)) {
exchange(input, i++, lt++);
} else if (less(pivot2, input[i])) {
exchange(input, i, gt--);
} else {
i++;
}
}
exchange(input, lowIndex, --lt);
exchange(input, highIndex, ++gt);
sort(input, lowIndex, lt - 1);
sort(input, lt + 1, gt - 1);
sort(input, gt + 1, highIndex);
}
}
用以下代码测试耗时:
int RANGE = 1000;
int SIZE = 1000 * 10000;
int[] data = new int[SIZE];
Random rdm = new Random();
for (int i = 0; i < SIZE; i++) {
data[i] = rdm.nextInt() % RANGE;
}
int[] tem = Arrays.copyOf(data, data.length);
long start = System.currentTimeMillis();
new QuickSortBasic().sort(tem);
System.out.println("basic:" + (System.currentTimeMillis() - start));
tem = Arrays.copyOf(data, data.length);
start = System.currentTimeMillis();
new QuickSort3Way().sort(tem);
System.out.println("3 way:" + (System.currentTimeMillis() - start));
tem = Arrays.copyOf(data, data.length);
start = System.currentTimeMillis();
new QuickSortDualPivot().sort(tem);
System.out.println("dual privot:" + (System.currentTimeMillis() - start));
结果大约是:
RANGE/SIZE
100,000/10,000,000basic:1150
3 way:1006
dual privot:1382
1,000/10,000,000
basic:1009
3 way:679
dual privot:23569
100/10,000,000
basic:949
3 way:430
Exception in thread "main" java.lang.StackOverflowError
1,000,000/1,000,000
basic:151
3 way:147
dual privot:115
发现在重复数据多的时候,还是三路快速排序效率高.双基准排序只有在重复数据不够多的情况下效率才会超过三路排序.
对这些算法不是很熟.只是根据那篇文章学到的.如果有问题,就评论一下.谢谢!
下面把剩下两个算法记一下,以便以后学习:
快速排序基本排序:
package test;
public class QuickSortBasic extends QuickSort {
public void sort(int[] input) {
sort(input, 0, input.length - 1);
}
private void sort(int[] input, int lowIndex, int highIndex) {
if (highIndex <= lowIndex) {
return;
}
int partIndex = partition(input, lowIndex, highIndex);
sort(input, lowIndex, partIndex - 1);
sort(input, partIndex + 1, highIndex);
}
private int partition(int[] input, int lowIndex, int highIndex) {
int i = lowIndex;
int pivotIndex = lowIndex;
int j = highIndex + 1;
while (true) {
while (less(input[++i], input[pivotIndex])) {
if (i == highIndex)
break;
}
while (less(input[pivotIndex], input[--j])) {
if (j == lowIndex)
break;
}
if (i >= j)
break;
exchange(input, i, j);
}
exchange(input, pivotIndex, j);
return j;
}
}
package test;
public class QuickSort3Way extends QuickSort {
public void sort(int[] input) {
sort(input, 0, input.length - 1);
}
public void sort(int[] input, int lowIndex, int highIndex) {
if (highIndex <= lowIndex)
return;
int lt = lowIndex;
int gt = highIndex;
int i = lowIndex + 1;
int pivotIndex = lowIndex;
int pivotValue = input[pivotIndex];
while (i <= gt) {
if (less(input[i], pivotValue)) {
exchange(input, i++, lt++);
} else if (less(pivotValue, input[i])) {
exchange(input, i, gt--);
} else {
i++;
}
}
sort(input, lowIndex, lt - 1);
sort(input, gt + 1, highIndex);
}
}