我想測試不同排序算法的執行時間,我發現了一個有趣的問題。當我多次運行該程序時,比如說插入排序,第一次或第二次比以後的花費更多時間。這種情況發生在數組的大小很大時,不同的大小對執行時間有不同的影響。爲什麼程序的執行時間會發生顯着變化?
public static void insertSort(int[] array){
for(int i = 1; i<array.length; i++){
int current = array[i];
int j = i-1;
while((j>=0)&&(array[j]>current)){
array[j+1] = array[j];
array[j] = current;
j--;
}
}
}
public static void multiTimes(int size){
Random r = new Random();
int a[] = new int[size];
int b[] = new int[size];
for(int j = 0; j<size; j++)
a[j] = r.nextInt(size);
long startTime, endTime = 0;
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
b = Arrays.copyOf(a, a.length);
startTime=System.nanoTime();
insertSort(b);
endTime=System.nanoTime();
System.out.println("Insert "+(endTime-startTime)+" ns");
}
面積:100
插入77908個納秒
插入82573個納秒
插入75109個納秒
插入76508個納秒
插入91902個納秒
插入78840個納秒
每次的執行時間很相似。
尺寸:1000:
插入6256400納秒
插入5674659納秒
插入188938納秒
插入188004納秒
插入187071納秒
插入186605納秒
尺寸:2000:
插入7961037 ns
插入6590889 ns
插入793538 NS
插入793072納秒
插入793072納秒
插入792138納秒
我們可以看到,對於1000,2000以上的尺寸,結果相當有趣。前兩次的執行時間比後面的執行時間大約多30倍(大小= 1000)。
注:
- 語言:Java的JDK7; IDE:Eclipse;平臺:Win8.1;
- 對於每個尺寸,許多實驗都經過測試,結果非常相似。儘管執行時間有一些隨機性,但它無法解釋爲什麼前兩次相似,比後一次長30倍以上。
- 一個可能的原因可能是該數組已經在數據高速緩存中,因此稍後的執行會花費更少的時間。我不確定是否有其他原因。
PS: 當我測試了插入排序後,我發現它在快速排序時甚至感到困惑。
public static void quickSort(int a[], int left, int right){
if(right<=left)
return;
int temp[] = new int[right-left+1];
for(int i = left; i<=right; i++)
temp[i-left] = a[i];
int pivot = a[left];
int subr = right, subl = left;
for(int i = left+1; i<=right;i++){
if(temp[i-left]>pivot)
a[subr--] = temp[i-left];
else
a[subl++] = temp[i-left];
}
a[subl] = pivot;
quickSort(a, left, subl-1);
quickSort(a, subr+1, right);
}
尺寸= 1000:
Qs的888240納秒
Qs的2218734納秒
Qs的2179547納秒
Qs的2132896納秒
Qs的2146890納秒
Qs的2212670納秒
尺寸= 500:
Qs 432924 ns
Qs 406799 ns
Qs的941889納秒
Qs的1103302納秒
Qs的1101436納秒
Qs的1086042納秒
當尺寸圍繞[200,2000]中,第一幾次花費的時間少於後來者,這是相對比插入排序。當大小增加到2000以上時,它與插入排序中的情況類似,後者的執行花費更少的時間。
這可能是一個可能的原因,但是,當我嘗試快速排序時,前幾次花費的時間相反。還有其他更多的原因? – Sentimental 2014-09-21 21:33:22