我想测试不同排序算法的执行时间,我发现了一个有趣的问题。当我多次运行该程序时,比如说插入排序,第一次或第二次比以后的花费更多时间。这种情况发生在数组的大小很大时,不同的大小对执行时间有不同的影响。为什么程序的执行时间会发生显着变化?
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