冒泡排序的优化

在面试的时候我们经常会被问到排序,比如有插入排序,冒泡排序等等,我们今天就讲下冒泡排序以及优化。
一想到冒泡排序马上就会想起使用双循环来实现:
先定义一个数组 int[] array = {3,4,2,1,5,7,6};
然后定义方法
public static void sort1(int[] array){
int temp;
for(int i=0;i<array.length-1;i++){
for(int j=0;j<array.length-1-i;j++){
if(array[j]>array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println(Arrays.toString(array));
}
}
这样就是我们最常见的冒泡排序,但是通过每次排完需,我们会发现有点问题,比如上面这个方法的执行过程:
[3, 2, 1, 4, 5, 6, 7]
[2, 1, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]

我们会发现从第4次开始,后面每次打印的都是一样的结果,这显然效率不高,既然这样,那肯定可以优化的。
我们先观察下排序后的结果,第一次排序后的结果是:
[3, 2, 1, 4, 5, 6, 7]
在排序的过程中,第j 都会和第j+1位做比较,这其实是可以不用这样的,
我们可以加个标记,也就是在第一个for循环中加个标记,标记当前是否是有序数组,若是,则跳出循环;
我们在定义一个方法,对刚才的排序进行优化:
public static void Optimize1(int array[]){
int temp=0;
for(int i=0;i<array.length;i++){
//有序标记,每一轮的初始是true
boolean isSorted = true;
for(int j=0;j<array.length-i-1;j++){
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
//有元素交换,所以不是有序,标记为false
isSorted = false;
}
}
if(isSorted){
break;
}
System.out.println(Arrays.toString(array));
}
}
排序的执行过程如下:
[3, 2, 1, 4, 5, 6, 7]
[2, 1, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
只执行了三次就排好了,这比第一种方法效率要高;
但是这还不是最高效的,我们再观察下,发现第一次排完序后
[3, 2, 1, 4, 5, 6, 7]
4,5,6,7 已经是一个有序数列了,那可不可以这样,每次排完序后,标记最后一次排序的位置,下次再对比的时候,只要对比到上次
最后的一个位置即可,因为上次排完序后的最后一个位置开始,到数组完,一定是一个有序数列。
所以冒泡排序最优版如下:
public static void sort(int array[]){
int temp =0;
//记录每次最后一次交换的位置
int lastExchangeIndex =0;
//无序数列边界,每次比较只需比到这里为止
int sortBorder = array.length-1;
for(int i=0;i<array.length;i++){
//有序标记,每一轮的初始是true
boolean isSorted = true;
for(int j=0;j<sortBorder;j++){
if(array[j]>array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
//有元素交换,所以不是有序,标记为false
isSorted = false;
//把无序数列的边界更新为最后一次元素交换的位置
lastExchangeIndex = j;
}
}
//更新无序数列边界
sortBorder = lastExchangeIndex;
if(isSorted){
break;
}
System.out.println(Arrays.toString(array));
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值