上一篇文章我学习了使用Java实现了最简单的插入排序算法(InsertionSort)。今天接续跟着马士兵老师学习,他讲到了这个程序还有两个待优化的地方。
1.看下面代码:
static void sort(int[] array){
for(int i = 1;i<array.length;i++){
//数组的第一个元素被当作已经排好序的一个数,所以i从1开始。
for(int j = i;j>0;j--){
if(array[j]<array[j-1]){
swap(array,j,j-1);
}
}
}
}
上面的代码中,内层的for循环里面有一个条件:if(array[j]<array[j-1])。这个条件可以放到for循环判断条件里面。代码是变成下面的样子:
static void sort(int[] array){
for(int i = 1;i<array.length;i++){
//数组的第一个元素被当作已经排好序的一个数,所以i从1开始。
for(int j = i; j>0&&a[j]<a[j-1]; j--){
swap(array,j,j-1);
}
}
}
以我的水平,我只能感觉代码少了一行,还不太明白这样的具体好处是什么。哈哈,问题先留着,以后再解决。
2.修改算法,使用临时变量记录标记项,去掉swap()方法。
这是之前的代码段:
static void sort(int[] array){
for(int i = 1;i<array.length;i++){
//数组的第一个元素被当作已经排好序的一个数,所以i从1开始。
for(int j = i;j>0;j--){
if(array[j]<array[j-1]){
swap(array,j,j-1);
}
}
}
}
static void swap(int[] array,int i,int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
之前的算法不停的调用swap()方法使数组元素归位,调用函数会带来一些开销的:
调用函数的开销大致可分两个部分:①传递参数的开销②保存当前程序上下文信息所花费的开销。对于传递参数的开销而 言,传递的参数越多开销就越大;对于保存当前程序上下文所花费的开销而言,函数越复杂需要花费的开销就越大。
sort函数调用swap()方法,参数是一个数组,程序还要保存上下文。为了减少开销提高效率,可使用临时变量记录标记项,去掉swap()方法。
使用临时变量temp,思路如下图所示:当需要把 2 插入到它前面的序列时,用temp保存2,之前的元素不断向后移动(a[j]=a[j-1]),这样一来就给2腾开了它该在的位置,然后将temp赋值给那个位置。
修改后的代码(修改后性能提升,我给它取名叫:sortPlus() 哈哈哈):
static void sortPlus(int[] a){
int temp = 0;
int j;
for(int i=1;i<a.length;i++){
for(j = i;j > 0;j--){
if(a[j]<a[j-1]){
temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}
}
}
}
这样就不用总调用swap()了。
代码修改完毕,我们通过数据看一下sort() 和 sortPlus()。自己写了一下测试代码:
我让两个程序都执行十万次,看看他们的执行时间
static void testSort(int [] a){
long startTime = System.currentTimeMillis(); //获取开始时间
for(int i = 0; i<100000;i++){
sort(a);
}
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("十万次sort()运行时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
long startTime1 = System.currentTimeMillis(); //获取开始时间
for(int i = 0; i<10000;i++){
sort(a);
}
long endTime1 = System.currentTimeMillis(); //获取结束时间
System.out.println("十万次sortPlus()运行时间:" + (endTime1 - startTime1) + "ms"); //输出程序运行时间
}
在main() 方法中调用:
public class InsertionSort {
public static void main(String[] args) {
int [] a = {6,5,2,4,9,7,8,5,1,4};
print(a);
//sort(a);
//sortPlus(a);
//print(a);
testSort(a);
}
执行结果:
可以看到在程序执行十万次的情况下,SortPlus()是Sort()运行时间的1/5 !
把十万再增大一下变成一百万看看:
一百万次下SortPlus()的运行时间大约是Sort()运行时间的1/10。
上面测试我只考虑了运行次数,应该还要测试在大量待排序数据数据下的运行效率。