在实现对快速排序分区的改进时,我试图使用Tukey的ninther来找到pivot(几乎借鉴了sedgewick在QuickX.java中的所有实现)
下面的代码每次对整数数组进行洗牌时都会给出不同的结果。
import java.util.Random;
public class TukeysNintherDemo{
public static int tukeysNinther(Comparable[] a,int lo,int hi){
int N = hi - lo + 1;
int mid = lo + N/2;
int delta = N/8;
int m1 = median3a(a,lo,lo+delta,lo+2*delta);
int m2 = median3a(a,mid-delta,mid,mid+delta);
int m3 = median3a(a,hi-2*delta,hi-delta,hi);
int tn = median3a(a,m1,m2,m3);
return tn;
}
// return the index of the median element among a[i], a[j], and a[k]
private static int median3a(Comparable[] a, int i, int j, int k) {
return (less(a[i], a[j]) ?
(less(a[j], a[k]) ? j : less(a[i], a[k]) ? k : i) :
(less(a[k], a[j]) ? j : less(a[k], a[i]) ? k : i));
}
private static boolean less(Comparable x,Comparable y){
return x.compareTo(y) < 0;
}
public static void shuffle(Object[] a) {
Random random = new Random(System.currentTimeMillis());
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + random.nextInt(N-i); // between i and N-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
public static void show(Comparable[] a){
int N = a.length;
if(N > 20){
System.out.format("a[0]= %dn", a[0]);
System.out.format("a[%d]= %dn",N-1, a[N-1]);
}else{
for(int i=0;i<N;i++){
System.out.print(a[i]+",");
}
}
System.out.println();
}
public static void main(String[] args) {
Integer[] a = new Integer[]{17,15,14,13,19,12,11,16,18};
System.out.print("data= ");
show(a);
int tn = tukeysNinther(a,0,a.length-1);
System.out.println("ninther="+a[tn]);
}
}
Running this a cuople of times gives
data= 11,14,12,16,18,19,17,15,13,
ninther=15
data= 14,13,17,16,18,19,11,15,12,
ninther=14
data= 16,17,12,19,18,13,14,11,15,
ninther=16
对于同一数据集的不同混洗,tuckey的ninther会给出不同的值吗?当我试图用手求中值时,我发现代码中的上述计算是正确的。。这意味着同一数据集产生不同于数据集中值的结果。这是正确的行为吗?在统计学方面有更多知识的人可以发表评论吗?
Tukey的ninther检查了9个项目,并仅使用来计算中位数。
对于不同的随机洗牌,你很可能会得到不同的Tukey的ninther,因为不同的项目可能会被检查。毕竟,您总是检查相同的数组插槽,但不同的洗牌可能会在这些插槽中放入不同的项目。
这里的关键是Tukey的ninther是,而不是给定数组的中值。这是一种尝试对中位数进行近似的方法,只需付出很少的努力:我们只需阅读9个项目并进行12次比较就可以得到它。这比得到实际中位数要快得多,而且与"三的中位数"相比,产生不希望的转折的可能性更小。请注意,机会仍然存在。
这能回答你的问题吗?
顺便说一句,有人知道使用Tukey的ninther进行快速排序是否还需要洗牌吗?我想是的,但我不确定。