1. 程式人生 > >Algs4-2.3.25切換到插入排序的試驗

Algs4-2.3.25切換到插入排序的試驗

進行 std and 18C sso local 索引 eight red

2.3.25切換到插入排序。實現一個快速排序,在子數組元素少於M時切換到插入排序。用快速排序處理大小N分別為10^3、10^4、10^5和10^6的隨機數組,根據經驗給出使其在你的計算環境中運行速度最快的M值。將M從0變化到30的每個值所得到的平均運行時間繪成曲線。註意:你需要為算法2.2添加一個需要三個參數的sort()方法以使Insertion.sort(a,lo,hi)將子數組a[lo..hi]排序。
答:
1)使用10^6長度的數組,M從2到99,進行了100次測試,排序用時最少的M在6至25之間,其中M=11時,排序用時最少的次數出現最多。具體有:M=11時 15次用時最少,M=15時 12次用時最少,M=13時 12次用時最少,M=10時 11次用時最少。

2)見圖
技術分享圖片


import java.awt.Color;
public class E2d3d25
{
public static void sort(Comparable[] a,int M)
{
//StdRandom.shuffle(a);
sort(a,0,a.length-1,M);
}

private static void sort(Comparable[] a,int lo,int hi,int M)
{
//數組少於等於M個元素時使用插入排序
if (hi-lo+1<M)
{
InsertSort(a,lo,hi);
return;
}
int j=partition(a,lo,hi);

sort(a,lo,j-1,M);
sort(a,j+1,hi,M);
}

private static int partition(Comparable[] a,int lo,int hi)
{
int i=lo,j=hi+1;
Comparable v=a[lo];
while(true)
{
while(less(a[++i],v)) if(i==hi) break;
while(less(v,a[--j])) if(j==lo) break;

if(i>=j) break;
exch(a,i,j);
}
exch(a,lo,j);
return j;
}


private static void InsertSort(Comparable[] a,int lo,int hi)
{
for (int i=lo+1;i<hi+1;i++)
{
for (int j=i;j>0 && less(a[j],a[j-1]);j--)
exch(a,j,j-1);
}
}

private static boolean less(Comparable v,Comparable w)
{ return v.compareTo(w)<0;}

private static void exch(Comparable[] a,int i,int j)
{
Comparable t=a[i];
a[i]=a[j];
a[j]=t;
}

private static void show(Comparable[] a)
{
for (int i=0;i<a.length;i++)
StdOut.print(a[i]+" ");
StdOut.println();
}

public static boolean isSorted(Comparable[] a)
{
for (int i=1;i<a.length;i++)
if(less(a[i],a[i-1])) return false;
return true;
}
public static void bestM()
{
//用來記錄M不同值時排序花費的時間
Double[] T=new Double[100];
//使用一個10^6方的數組進行排序測試
int N=1000000;
Double[] a=new Double[N];
for(int i=0;i<N;i++)
a[i]=StdRandom.random();
//子數組最小長度只可能是1,所以M必須從1開始
//跳過為0、1的索引使得索引與M一一直接對應
for(int M=2;M<T.length;M++)
{
//對於不同的M使用相同的排列進行排序
Double[] aClone=new Double[a.length];
for(int i=0;i<a.length;i++)
aClone[i]=a[i];
//開始排序並計時
Stopwatch timer=new Stopwatch();
sort(aClone,M);
T[M]=timer.elapsedTime();
//StdOut.printf("%d\t%f\n",M,T[M]);
}//end for M
//找出用時最小的M
int minM=2;
for(int i=3;i<T.length;i++)
if (less(T[i],T[minM])) minM=i;
StdOut.println("best M=" +minM);
}//end bestM

public static void drawAverageTime()
{
//
StdDraw.setXscale(0,35);
StdDraw.setYscale(-0.5,3);
//
int Nlen[]={100000,1000000,3000000};//
for(int Ni=0;Ni<Nlen.length;Ni++)
{
int N=Nlen[Ni];
//生成一個長度為N的數組a
Double[] a=new Double[N];
for(int i=0;i<N;i++)
a[i]=StdRandom.random();
//M從0至30對數對組a的副本進行排序,同一長度的N,不同的M時待排序數組內容相同
Double totalTime=0.0;
StdDraw.setPenColor(Color.BLACK);
StdDraw.setPenRadius(0.02);
for(int M=2;M<=30;M++)
{
//生成一個數組a的副本aClone
Double[] aClone=new Double[N];
for (int i=0;i<a.length;i++)
aClone[i]=a[i];
//數組長度為N,小於等於M時切換到插入排序的快速排序
Stopwatch timer=new Stopwatch();
sort(aClone,M);
totalTime=totalTime+timer.elapsedTime();
StdDraw.point(M,timer.elapsedTime());
}//end for M
StdDraw.setPenColor(Color.RED);
StdDraw.setPenRadius(0.01);
StdDraw.line(2,totalTime/29,30,totalTime/29);
}//end for Ni
}

public static void main(String[] args)
{
//for (int i=0;i<100;i++)
// bestM();
drawAverageTime();

}//end main
}//end class

Algs4-2.3.25切換到插入排序的試驗