依照书上写了3段代码,分别是以右端数据、首中尾取中值、先找出中间值作为枢纽,使用一百万随机数测试后发现,原始的快排最快,先找中间值的反而最慢。
代码如下
1:原始的
package LianXi;
import java.util.Arrays;
import java.util.Random;
//快速排序:先以数组末端作为标准,大于它的左端元素和小于它的右端元素作为一对进行交换
//最后将枢纽数据换到第二个数组首位
public class FastSort {
static int i;
static void sort(int[] a, int front, int end) {
if (front >= end)
return;
i = div(a, front, end);
sort(a, front, i - 1);
sort(a, i + 1, end);
}
static int div(int[] a, int front, int end) {
int temp = a[end];
int l = front - 1;
int r = end;
while (true) {
while (a[++l] < temp)
;
while (r > 0 && a[--r] > temp)
;// 找到然后交换,while很精巧
if (l >= r)
break;
else
swap(a, l, r);
}
swap(a, l, end);
return l;// 返回右边数组首位下标
}
static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
long t1=System.currentTimeMillis();
int size = 100;
int[] a = new int[size];
Random rand = new Random();
for (int i = 0; i < 20; i++) {
int n = rand.nextInt(size*5);
a[i] = n;
}
sort(a, 0, a.length - 1);
long t2=System.currentTimeMillis();
System.out.println(t2-t1);
}
}
2:先从首、中、尾找出中间值作为枢纽元素
package LianXi;
import java.util.Random;
public class FastSort2 {
// 中值划分至少要4个数据,不然另外解决
static void sort(int[] a, int front, int end) {
int size = end - front + 1;
if (size <= 3)//这里是可调节的地方,对于数据量50000来说,设置3或者10都好像没有区别
manualsort(a, front, end);
else {
int temp = div(a, front, end);
sort(a, front, temp - 1);
sort(a, temp + 1, end);
}
}
static int div(int[] a, int front, int end) {
int temp = innersort(a, front, end);// temp接收中间值
int left = front;
int right = end - 1;
while (true) {
while (a[++left] < temp)
;
while (a[--right] > temp)
;
if (left >= right)
break;
else
swap(a, left, right);
}
swap(a, end - 1, left);
return left;
}
static int innersort(int[] a, int i, int j) {
int mid = (i + j) / 2;
if (a[i] > a[mid])
swap(a, i, mid);
if (a[i] > a[j])
swap(a, i, j);
if (a[mid] > a[j])
swap(a, mid, j);
swap(a, mid, j - 1);// 把中间值移到倒数第二个
return a[j - 1];
}
static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
// 需要注意下标可能出现左边大于右边的情况
static void manualsort(int[] a, int front, int end) {
if (front >= end)
return;
else {
for (int i = front + 1; i <= end; i++) {
int j = i;
int temp=a[i];
while (--j >= front && a[j] > temp)
a[j + 1] = a[j];
a[j + 1] = temp;
}
}
}
public static void main(String[] args) {
long t1=System.currentTimeMillis();
int size = 100;
int[] a =new int[size];
Random rand = new Random();
//System.out.println("排序前:");
for (int i = 0; i < a.length; i++) {
int n = rand.nextInt(size*2);
//System.out.print(n + " ");
a[i] = n;
}
sort(a, 0, a.length - 1);
//System.out.println("\n排序后:");
//System.out.println(Arrays.toString(a));
long t2=System.currentTimeMillis();
System.out.println(t2-t1);
}
}
3:先找出整个数组中间值,再排序
package LianXi;
import java.util.Random;
//先利用快排找出中间值
public class FindMid {
static int[] a;
static int mid;
static void finalsort() {
find(0, a.length - 1);// 中值已在中间
swap(mid, a.length - 1);// 将中间值换到最后
sort(0, a.length - 1);
}
static void sort(int f, int end) {
if (end - f <= 0)
return;
int temp = div(f, end);
sort(f, temp - 1);
sort(temp + 1, end);
}
static void find(int f, int end) {
if (end - f == 1) {
if (a[f] > a[end])
swap(f, end);
return;// 如果只剩2个,排完即返回
}
int m = (f + end) / 2;
int temp = div(f, end);
if (temp == mid)// 如果枢纽下标为这个,说明枢纽即是中间值
return;
if (temp > m)
find(f, temp - 1);// 这里不-1会无限循环
else if (temp < m)
find(temp + 1, end);
else if (temp == m) {
if (m > mid)
find(f, temp - 1);
else
find(temp + 1, end);
}
}
// 划分一次,返回枢纽下标
static int div(int f, int end) {
int l = f - 1;
int r = end;
int temp = a[end];
while (true) {
while (a[++l] < temp)
;
while (r > l && a[--r] > temp)
;
if (r <= l)
break;
else
swap(r, l);
}
swap(end, l);
return l;
}
static void swap(int f, int end) {
int temp = a[f];
a[f] = a[end];
a[end] = temp;
}
public static void main(String[] args) {
long t1=System.currentTimeMillis();
int size = 100;
a = new int[size];
mid = (a.length - 1) / 2;// 这里可以选择自己想要的下标,得出的值就是第几大
Random rand = new Random();
for (int i = 0; i < size; i++) {
int n = rand.nextInt(size * 5);
a[i] = n;
}
finalsort();
long t2=System.currentTimeMillis();
System.out.println(t2-t1);
}
}
第三个可以用做找出一个数组的第n大数据而不去排序它。