冒泡排序是排序算法里面较为简单的一种排序方法,两年前学习该排序算法时,总是很懵,不知道它和选择排序有什么区别,随着学习的深入,我理解了它为什么要叫做冒泡排序。
之所以叫冒泡,我们可以想象一个现象。桶里面装了一桶水,我们扔下一块石头,那么桶里面的水是不是会冒出一连串的水泡到水面上炸开。石头就相当于是一个待比较的数,它进去和水里面的其它数作比较,遇到比它大(小)的就去和它交换位置,然后大(小)的数就继续往下走,去交换更大(小)的数到水面上来。 这就是为什么要叫冒泡排序。
接下来,我将用代码具体实现其基本操作,并对其进行简单的优化:
基础版冒泡排序:
待排序的数组:{9,8,7,6,5} ,我们将其从小到大排序
第一趟:找出最大的数 9
第一次 {8,9,7,6,5} 8和9交换
第二次 {8,7,9,6,5} 7和9交换
第三次 {8,7,6,9,5} 6和9交换
第四次 {8,7,6,5,9} 5和9交换
第二趟 找出第二大的数 8
第一次 {7,8,6,5,9} 7和8交换
第二次 {7,6,8,5,9} 6和8交换
第三次 {7,6,5,8,9} 5和8交换
第四次 {7,6,5,8,9} 8和9交换
第三趟 找出第三大的数 7
第一次 {6,7,5,8,9} 6和7交换
第二次 {6,5,7,8,9} 5和7交换
第三次 {6,5,7,8,9} 7和8交换
第四次 {5,6,7,8,9} 8和9交换
第四趟 找出第四大的数
第一次 {5,6,7,8,9} 5和6交换
第二次 {5,6,7,8,9} 6和7交换
第三次 {5,6,7,8,9} 7和8交换
第四次 {5,6,7,8,9} 8和9交换
代码实现:`
public static void sort(int[] a){
int len = a.length;
for (int i = 0;i < len-1;i++){
// System.out.println("第"+(i+1)+"趟:");
for (int j = 0;j < len-1;j++){
//System.out.println("第"+(j+1)+"次:");
if (a[j] > a[j+1]){ //每一趟将最大的冒出来
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
System.out.println(Arrays.toString(a));
}
}
}
输出结果:
第1趟:
第1次:
[8, 9, 7, 6, 5]
第2次:
[8, 7, 9, 6, 5]
第3次:
[8, 7, 6, 9, 5]
第4次:
[8, 7, 6, 5, 9]
第2趟:
第1次:
[7, 8, 6, 5, 9]
第2次:
[7, 6, 8, 5, 9]
第3次:
[7, 6, 5, 8, 9]
第4次:
[7, 6, 5, 8, 9]
第3趟:
第1次:
[6, 7, 5, 8, 9]
第2次:
[6, 5, 7, 8, 9]
第3次:
[6, 5, 7, 8, 9]
第4次:
[6, 5, 7, 8, 9]
第4趟:
第1次:
[5, 6, 7, 8, 9]
第2次:
[5, 6, 7, 8, 9]
第3次:
[5, 6, 7, 8, 9]
第4次:
[5, 6, 7, 8, 9]
通过上面的一步步的展现,我们可以发现,很多比较是重复在进行,那么我们想是不是可以将重复的次数减下来。通过观察发现,第一趟比较4次,第二趟比较3次,以此类推。可以得出每一趟的趟数+次数也就是代码中i+j始终是等于4。那我们就可以归纳出,次数比较里面循环的条件改为(j < len-1-i) 这样就能有效减少重复次数
代码如下:
改进版冒泡排序
public static void sort2(int[] a){
int len = a.length;
for (int i = 0;i < len-1;i++){
//System.out.println("第"+(i+1)+"趟:");
for (int j = 0;j < len-1-i;j++){
//System.out.println("第"+(j+1)+"次:");
if (a[j] > a[j+1]){ //每一趟将最大的冒出来
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
System.out.println(Arrays.toString(a));
}
}
}
运行结果:
此时,每一次循环比较的次数明显减少了。
那么,要是数组本来就已经是有序的了或者说经过几趟之后有序了,剩下的几趟我们是不是可以不再进行下去了呢?很显然是可以的,我们可以设定一个Boolean的类型的变量来判断其是否已经有序,如下:
public static void sortFinal(int[] a){
System.out.println("***************final version*******************");
boolean sorted = true; //判断是否有序
int len = a.length;
for (int i = 0;i < len-1;i++){
sorted = true; //假定有序
System.out.println("第"+(i+1)+"趟:");
for (int j = 0;j < len-1-i;j++){
System.out.println("第"+(j+1)+"次:");
if (a[j] > a[j+1]){ //每一趟将最大的冒出来
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
sorted = false;
}
System.out.println(Arrays.toString(a));
}
if (sorted){ //如果没有交换,则退出循环,减少趟数
break;
}
}
}
运行结果如下:
终极版冒泡排序
我认为冒泡排序能改进到这样了,应该是比较完美的了,如果还有更好的改进方式,希望大家多多指正。