冒泡排序

176 阅读4分钟

一、什么是冒泡

这里开始写冒泡排序的时候就写成了选择排序...专门去百度了下什么是冒泡排序。

冒泡排序算法的原理如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
百度百科解释的够全面了,顾名思义的话,元素就像气泡一样向水面上浮。

二、一级冒泡

private static void myPaoSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            // 内层比较次数
            int times = 0;
            int temp;
            for (int j = 0; j < array.length - i - 1; j++) {
                times++;
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
            System.out.println("第" + i + "层:" + "内层比较次数为:" + times);
        }
    }

这里初始化数组为:

int[] sorts = new int[]{1, 3, 2, 4, 5, 6, 7, 8, 9, 10};

输出如下:

第0层:内层比较次数为:9
第1层:内层比较次数为:8
第2层:内层比较次数为:7
第3层:内层比较次数为:6
第4层:内层比较次数为:5
第5层:内层比较次数为:4
第6层:内层比较次数为:3
第7层:内层比较次数为:2
第8层:内层比较次数为:1

结论:

 1、时间复杂度为O(n²)
 2、观察初始化数组发现,第四个元素之后的元素已经是有序的了,外层循环只需要循环2次后就不需要再遍历排序。

三、 二级冒泡

遂对代码进行优化,如下:

private static void myPaoSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            // 内层比较次数
            int times = 0;
            int temp;
            boolean flagOut = true;

            for (int j = 0; j < array.length - i - 1; j++) {
                times++;
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    // 只要交换了 flag就等于false;
                    flagOut = false;
                }
            }
            System.out.println("第" + i + "层:" + "内层比较次数为:" + times);
            // 一直没交换 说明之后的已经是有序
            if (flagOut) {
                break;
            }
        }
    }

输出如下:

第0层:内层比较次数为:9
第1层:内层比较次数为:8

结论:

 1、时间复杂度为O(n²)
 2、这里用了一个标志flagOut去标记数组有没有交换,我自己再开始做优化的时候,一直再纠结没有交换的时候才改变flagOut 的值, 写的很复杂。后来看资料发现,换个角度,当每次交换的时候我都把 flagOut 置为false,然后再外层循环结束的时候比较flagOut为true,为true就说明一直没交换,为什么没交换呢?不就是因为已经是有序的么。不就没毛病了么。不太聪明的亚子啊...
 3、但是,内层循环还是再循环那些已经排好序的元素。

四、 三级冒泡

遂对代码进行优化,如下:

private static void myPaoSort(int[] array) {
       for (int i = 0; i < array.length - 1; i++) {
           // 内层比较次数
           int times = 0;
           int temp;
           boolean flagOut = true;
           // 初始边界值
           int sortBorder = array.length - 1;
           for (int j = 0; j < sortBorder; j++) {
               times++;
               if (array[j] > array[j + 1]) {
                   temp = array[j];
                   array[j] = array[j + 1];
                   array[j + 1] = temp;
                   // 只要交换了 flag就等于false;
                   flagOut = false;
                   // 只要交换,就更新有序边界值
                   sortBorder = j;
               }
           }
           System.out.println("第" + i + "层:" + "内层比较次数为:" + times);
           // 一直没交换 说明之后的已经是有序
           if (flagOut) {
               break;
           }
       }
   }

输出如下:

第0层:内层比较次数为:2
第1层:内层比较次数为:9

结论:

 1、时间复杂度为O(n²)
 2、显然内层循环次数变少了,这里用sortBorder 用来标志 数组中的有序边界,即已经排好序的元素。这样冒泡的内外层都进行了优化。
 3、 等等,你以为就这么优化算完事了?输出结果为什么第二次循环的时候内层比较的次数比第一次循环还要多?
 问号脸.png ...
 调试发现, 边界值sortBorder 在每次外层循环的时候都特么被初始化成了  array.length - 1。
 游乐王子: 真的是不太聪明的亚子。
 微笑脸.png ...

五、 终极冒泡

遂对代码进行优化,如下:

private static void myPaoSort(int[] array) {
       // 初始比较值, 最终优化 冒泡
       int sortBorder = array.length - 1;
       for (int i = 0; i < array.length - 1; i++) {
           // 内层比较次数
           int times = 0;
           int temp;
           boolean flagOut = true;
           for (int j = 0; j < sortBorder; j++) {
               times++;
               if (array[j] > array[j + 1]) {
                   temp = array[j];
                   array[j] = array[j + 1];
                   array[j + 1] = temp;
                   // 只要交换了 flag就等于false;
                   flagOut = false;
                   // 只要交换,就更新有序边界值
                   sortBorder = j;
               }
           }
           System.out.println("第" + i + "层:" + "内层比较次数为:" + times);
           // 一直没交换 说明之后的已经是有序
           if (flagOut) {
               break;
           }
       }
   }

输出如下:

第0层:内层比较次数为:2
第1层:内层比较次数为:1

结论:

 1、 时间复杂度为O(n²)
 2、 听说这还不是最终的优化...

溜了溜了, 结束摸鱼的一天,下班...