在诸多排序算法当中,冒泡算法应该是最简单入门的。如果让你写出一个对int数组的冒泡排序你会怎么写?
应该有不少的人会是如下的答案吧:
public static int[] sort2(int[] list){
for (int i=0;i for(int j=0;j if(j>0){
int listE1 = list[j-1];
int listE2 = list[j];
if(listE1 > listE2){
list[j-1]=listE2;
list[j]=listE1;
}
}
}
}
return list;
}
那么有没有更优的写法呢?
再公布答案之前,我想带大家聊聊冒泡算法的原理。假设现在拥有[5,2,8,17,4]这样的一个int数组。那么冒泡排序做的事情就是两两比较,大的哪一个排在后面的位置。为了更直观的了解,我把他的每一步排序过程做了如下拆分:
第一次排序结果:[2,5,8,17,4] 数字5大于数字2,所以5和2调换位置。
第二次排序结果:[2,5,8,17,4] 数字5小于数字8,所以5和8的位置不变。
第三次排序结果:[2,5,8,17,4] 数字8小于数字17,所以8和17的位置不变。
第四次排序结果:[2,5,8,4,17] 数字17大于数字4,所以17和4调换位置。
由此往复,最终就可以得到排序正确的int数组。仔细观察一下上面的四次排序过程,有没有发现在第一次从头到尾排序之后,最大的那个数被扔到了数组的末尾。
那么根据这个特性就可以写出一个性能较优于上面那个冒泡排序的算法:
public static int[] sort1(int[] list){
int listSize = list.length;
for (int i=0;i for(int j=0;j if(j>0){
int listE1 = list[j-1];
int listE2 = list[j];
if(listE1 > listE2){
list[j-1]=listE2;
list[j]=listE1;
}
}
}
listSize--;
}
return list;
}
这个算法在每次从头到尾的排序完成之后,内部循环就可以比上次少执行一次。性能如何做一个实验对比。
int[] intArray ={5,2,8,17,4,83,34,62,2,46,79};
long star = System.currentTimeMillis();
for(int i=0;i<=500000;i++){
sort1(intArray);
}
long end = System.currentTimeMillis();
System.out.println(end-star);
改进后的算法耗时77毫秒。
int[] intArray ={5,2,8,17,4,83,34,62,2,46,79};
long star = System.currentTimeMillis();
for(int i=0;i<=500000;i++){
sort2(intArray);
}
long end = System.currentTimeMillis();
System.out.println(end-star);
未改进的算法耗时93毫秒。
上面这个实验中改进后的算法比未改进的算法耗时减少了16毫秒。这个耗时会随着数组长度的增加而不断提升。为了验证这一推测,我又进行了如下实验:
int[] intArray ={5,2,8,17,4,83,34,62,2,46,79,3,9,15,64,76,7,24,45,88,44,84,134,43,92,43,643,16,18,32,35,19,10,45,764,12,85,24,987,52,18,754};
long star = System.currentTimeMillis();
for(int i=0;i<=500000;i++){
sort1(intArray);
}
long end = System.currentTimeMillis();
System.out.println(end-star);
改进后的算法耗时592毫秒。
int[] intArray =
{5,2,8,17,4,83,34,62,2,46,79,3,9,15,64,76,7,24,45,88,44,84,134,43,92,43,643,16,18,32,35,19,10,45,764,12,85,24,987,52,18,754};
long star = System.currentTimeMillis();
for(int i=0;i<=500000;i++){
sort2(intArray);
}
long end = System.currentTimeMillis();
System.out.println(end-star);
未改进的算法耗时1005毫秒。
这次他们之间的差距增加到了413毫秒。性能的优劣就不需要再做过多的总结了。上面实验中数组的构造均采用了手动创建而没有使用随机数生成,原因就在于为了消除随机数对实验结果的影响。这次分享到这里就告一段落了。