2.2.6编写一个程序来计算自顶向下和自底向上的归并排序访问数组的准确次数。使用这个程序将N=1至512的结果绘制成曲线图,并将其和上限6NlgN比较。
说明:Red线是6NlgN 、Green线是自顶向下、Blue线是自底向上。
public class Merge
{
private static Comparable[] aux;
public static int ArrayAccessTimes=0;
public static void sort(Comparable[] a)
{
aux=new Comparable[a.length];
sort(a,0,a.length-1);
}
public static void sort(Comparable[] a,int lo,int hi)
{
if (hi<=lo) return;
int mid=lo+(hi-lo)/2;
//StdOut.printf("lo=%d,mid=%d,mid+1=%d,hi=%d
",lo,mid,mid+1,hi);
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
public static void merge(Comparable[] a,int lo,int mid,int hi)
{
int i=lo,j=mid+1;
for (int k=lo;k<=hi;k++)
{aux[k]=a[k];ArrayAccessTimes=ArrayAccessTimes+2;}
for(int k=lo;k<=hi;k++)
if (i>mid) {a[k]=aux[j++];ArrayAccessTimes=ArrayAccessTimes+2;}
else if (j>hi) {a[k]=aux[i++];ArrayAccessTimes=ArrayAccessTimes+2;}
else if (less(aux[j],aux[i])) {a[k]=aux[j++];ArrayAccessTimes=ArrayAccessTimes+2;}
else {a[k]=aux[i++];ArrayAccessTimes=ArrayAccessTimes+2;}
}
private static boolean less(Comparable v,Comparable w)
{ return v.compareTo(w)<0;}
public static void main(String[] args)
{
StdDraw.setXscale(0.0,1.2*512);
StdDraw.setYscale(0.0,10*Math.log(512)/Math.log(2)*512.0);
StdDraw.setPenRadius(0.005);
for(int N=1;N<=512;N++)
{
Double[] a=new Double[N];
for(int i=0;i<N;i++)
a[i]=StdRandom.uniform();
ArrayAccessTimes=0;
sort(a);
//Draw 6NlgN
StdDraw.setPenColor(StdDraw.RED);
StdDraw.point(1.0*N,6.0*N*Math.log(N)/Math.log(2));
//Draw ArrayAccessTimes
StdDraw.setPenColor(StdDraw.BLUE);
StdDraw.point(1.0*N,1.0*ArrayAccessTimes);
// StdOut.printf("N=%d,ArrayAccessTimes=%d
",N,ArrayAccessTimes);
}
}
}
//
public class MergeBU
{
private static Comparable[] aux;
public static int ArrayAccessTimes=0;
public static void sort(Comparable[] a)
{
int N=a.length;
aux=new Comparable[N];
for(int sz=1;sz<N;sz=sz+sz)
for(int lo=0;lo<N-sz;lo+=sz+sz)
merge(a,lo,lo+sz-1,Math.min(lo+sz+sz-1,N-1));
}
public static void merge(Comparable[] a,int lo,int mid,int hi)
{
int i=lo,j=mid+1;
for (int k=lo;k<=hi;k++)
{aux[k]=a[k];ArrayAccessTimes=ArrayAccessTimes+2;}
for(int k=lo;k<=hi;k++)
if (i>mid) {a[k]=aux[j++];ArrayAccessTimes=ArrayAccessTimes+2;}
else if (j>hi) {a[k]=aux[i++];ArrayAccessTimes=ArrayAccessTimes+2;}
else if (less(aux[j],aux[i])) {a[k]=aux[j++];ArrayAccessTimes=ArrayAccessTimes+2;}
else {a[k]=aux[i++];ArrayAccessTimes=ArrayAccessTimes+2;}
}
private static boolean less(Comparable v,Comparable w)
{ return v.compareTo(w)<0;}
public static void main(String[] args)
{
StdDraw.setXscale(0.0,1.2*512);
StdDraw.setYscale(0.0,10*Math.log(512)/Math.log(2)*512.0);
StdDraw.setPenRadius(0.005);
for(int N=1;N<=512;N++)
{
Double[] a=new Double[N];
for(int i=0;i<N;i++)
a[i]=StdRandom.uniform();
ArrayAccessTimes=0;
sort(a);
//Draw 6NlgN
StdDraw.setPenColor(StdDraw.RED);
StdDraw.point(1.0*N,6.0*N*Math.log(N)/Math.log(2));
//Draw ArrayAccessTimes
StdDraw.setPenColor(StdDraw.BLUE);
StdDraw.point(1.0*N,1.0*ArrayAccessTimes);
// StdOut.printf("N=%d,ArrayAccessTimes=%d
",N,ArrayAccessTimes);
}
}
}
//
public class E2d2d6
{
public static void main(String[] args)
{
StdDraw.setXscale(0.0,1.2*512);
StdDraw.setYscale(0.0,10*Math.log(512)/Math.log(2)*512.0);
StdDraw.setPenRadius(0.005);
for(int N=1;N<=512;N++)
{
Double[] a=new Double[N];
for(int i=0;i<N;i++)
a[i]=StdRandom.uniform();
//Draw 6NlgN
StdDraw.setPenColor(StdDraw.RED);
StdDraw.point(1.0*N,6.0*N*Math.log(N)/Math.log(2));
//Draw Merge.ArrayAccessTimes
Merge.ArrayAccessTimes=0;
Merge.sort(a);
StdDraw.setPenColor(StdDraw.GREEN);
StdDraw.point(1.0*N,1.0*Merge.ArrayAccessTimes);
//Draw MergeBU.ArrayAccessTimes
MergeBU.ArrayAccessTimes=0;
MergeBU.sort(a);
StdDraw.setPenColor(StdDraw.BLUE);
StdDraw.point(1.0*N,1.0*MergeBU.ArrayAccessTimes);
}
}//end main
}//end class