冒泡排序学习及简单优化(java)

冒泡排序是排序算法里面较为简单的一种排序方法,两年前学习该排序算法时,总是很懵,不知道它和选择排序有什么区别,随着学习的深入,我理解了它为什么要叫做冒泡排序。

之所以叫冒泡,我们可以想象一个现象。桶里面装了一桶水,我们扔下一块石头,那么桶里面的水是不是会冒出一连串的水泡到水面上炸开。石头就相当于是一个待比较的数,它进去和水里面的其它数作比较,遇到比它大(小)的就去和它交换位置,然后大(小)的数就继续往下走,去交换更大(小)的数到水面上来。 这就是为什么要叫冒泡排序。

接下来,我将用代码具体实现其基本操作,并对其进行简单的优化:

基础版冒泡排序:
待排序的数组:{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;
            }
        }
    }

运行结果如下:
终极版冒泡排序
在这里插入图片描述
我认为冒泡排序能改进到这样了,应该是比较完美的了,如果还有更好的改进方式,希望大家多多指正。

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页