冒泡排序深入理解

冒泡排序

主要思想

冒泡排序的主要思想是“两两交换”。试想,我们拿到一个无序的一组数字,如果每次都把相邻的两个数排好位置,不停地循环,最终就会将所有数字排好位置。

举例

我们以数组 [1, 3, 4, -1, 4, -2, 32, 77, -1, -77] 为例。

第一轮两两比较:(1, 3)不交换,(3, 4)不交换,(4,-1)交换为(-1,4),(4,4)不交换,(4,-2)交换为(-2,4),(4,32)不交换,(32,77)不交换,(77,-1)交换为(-1,77),(77,-77)交换为(-77,77)

由此可见,第一轮结束后,数组变为[1,3,-1,4,-2,4,32,-1,-77,77]。最大数77已经排到了最后一位。

第二轮两两比较:(1,3)不交换,(3,-1)交换为(-1,3),(3,4)不交换,(4,-2)交换为(-2,4),(4,4)不交换,(4,32)不交换,(32,-1)交换为(-1,32),(32,-77)交换为(-77,32),(32,77)不交换。

由此可见,第二轮结束后,数组变为[1, -1, 3, -2, 4, 4, -1, -77, 32, 77],第二大的数32又排到了后面。

如此循环多轮,每一轮都可以将该轮最大的数排到最后,类似于每次都冒一个最大的泡泡上去,所以叫做冒泡排序。

需要冒多少轮?

这样来想,一个数组有n个数,每轮都将该轮最大的一个数冒泡上去,那么n轮肯定就全部数据都可以冒完。但是,最后一轮只有一个数了,所以也就不用再冒了。因此,可以看出,n个数的数组,需要冒泡n-1轮。

每轮需要比较多少次相邻的两个数?

从我们上面的举例可以推测,第一轮,n个数两两比较,需要比较n-1次。第二轮,因为在第一轮比较的基础上,一个数已经冒泡到最后,所以,比较次数就会变为n-2。第三轮,因为在第二轮比较的基础上,两个数已经冒泡到最后,所以,比较次数就会变为n-3。由此推出,第m轮,因为在m-1轮比较的基础上,m-1个数已经冒泡到最后,所以,比较次数就会变为n-m次。

回答这个问题,第m轮需要比较的次数为,数字的个数n - 轮数m。

代码:

    public static int[] bubleSort(int[] a) {
        //冒泡排序的核心思想是将数据两两比较,然后按照大小顺序交换位置
        for (int i = 0; i < a.length -1; i++) {
            //因为要两两比较,所以如果有n个数,就需要n-1轮,外层循环a.length-1次
            for (int i1 = 0; i1 < a.length - (i + 1); i1++) {
                //对于每一轮,因为每处理完一轮,就会少一个数字,因此内层循环只需要比较(n-轮数)次。
                if (a[i1] > a[i1+1]) {
                    int temp = a[i1];
                    a[i1] = a[i1+1];
                    a[i1+1] = temp;
                }
            }
            System.out.println(Arrays.toString(a));
        }
        return a;
    }
第1轮:[1, 3, -1, 4, -2, 4, 32, -1, -77, 77]
第2轮:[1, -1, 3, -2, 4, 4, -1, -77, 32, 77]
第3轮:[-1, 1, -2, 3, 4, -1, -77, 4, 32, 77]
第4轮:[-1, -2, 1, 3, -1, -77, 4, 4, 32, 77]
第5轮:[-2, -1, 1, -1, -77, 3, 4, 4, 32, 77]
第6轮:[-2, -1, -1, -77, 1, 3, 4, 4, 32, 77]
第7轮:[-2, -1, -77, -1, 1, 3, 4, 4, 32, 77]
第8轮:[-2, -77, -1, -1, 1, 3, 4, 4, 32, 77]
第9轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]

优化

因为冒泡排序的思想是相邻数字两两比较,所以,如果在某一轮,没有发生交换,那说明什么?思考一下就知道,那说明了当前相邻的每两个数都是有序的了。这样,还需要继续去循环吗?答案肯定是不需要了!

这样,我们就可以找到一个优化点,在代码中去判断在每一轮两两比较中,有没有发生过交换。如果没有发生过交换,那么,数字已经有序了,排序就可以结束。

举例数组换为:[-1, -77, 1, 3, 4, -1, 4, -2, 32, 77]

### 无优化循环9轮:
第1轮:[-77, -1, 1, 3, -1, 4, -2, 4, 32, 77]
第2轮:[-77, -1, 1, -1, 3, -2, 4, 4, 32, 77]
第3轮:[-77, -1, -1, 1, -2, 3, 4, 4, 32, 77]
第4轮:[-77, -1, -1, -2, 1, 3, 4, 4, 32, 77]
第5轮:[-77, -1, -2, -1, 1, 3, 4, 4, 32, 77]
第6轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
第7轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
第8轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
第9轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
    public static int[] bubleSort(int[] a) {
        //冒泡排序的核心思想是将数据两两比较,然后按照大小顺序交换位置
        for (int i = 0; i < a.length -1; i++) {
            //因为要两两比较,所以如果有n个数,就需要n-1轮,外层循环a.length-1次
            boolean swapped = false;
            for (int i1 = 0; i1 < a.length - (i + 1); i1++) {
                //对于每一轮,因为每处理完一轮,就会少一个数字,因此内层循环只需要比较(n-轮数)次。
                if (a[i1] > a[i1+1]) {
                    int temp = a[i1];
                    a[i1] = a[i1+1];
                    a[i1+1] = temp;
                    swapped = true;
                }
            }
            System.out.println("第"+(i+1)+"轮:"+Arrays.toString(a));
            if (!swapped) {
                return a;
            }
        }
        return a;
    }
### 优化后,只循环7轮
第1轮:[-77, -1, 1, 3, -1, 4, -2, 4, 32, 77]
第2轮:[-77, -1, 1, -1, 3, -2, 4, 4, 32, 77]
第3轮:[-77, -1, -1, 1, -2, 3, 4, 4, 32, 77]
第4轮:[-77, -1, -1, -2, 1, 3, 4, 4, 32, 77]
第5轮:[-77, -1, -2, -1, 1, 3, 4, 4, 32, 77]
第6轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
第7轮:[-77, -2, -1, -1, 1, 3, 4, 4, 32, 77]
posted @ 2020-11-07 10:53  SuperTC  阅读(201)  评论(0)    收藏  举报