给自己五分钟,彻底搞懂并优化冒泡排序

Posted DayFight_DayUp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给自己五分钟,彻底搞懂并优化冒泡排序相关的知识,希望对你有一定的参考价值。

冒泡排序思想

给定一个无序数组,让“重”的元素下沉,轻的元素上浮”,这个就是冒泡排序。

算法描述

1. 对于给定长度为N的数组, 我们从头进行N次扫描。
2. 每一次扫描相邻的两个元素进行大小比较,若某一元素大于它的下一个元素,就进行交换。
3. 每一次扫描都会把剩余元素的最大值下沉到剩余元素的末尾。故每扫描一次,下一次扫描的超度相应的就减一。

示例

假设要对 下面数组进行排序:

{5, 4, 12, 11, 19, 2, 1, 14}

第 1 趟扫描排序: 4 和 5 交换,12 和 11 交换, 19 下沉到数组末尾。

{4, 5, 11, 12, 2, 1, 14, 19}

第 2 趟扫描排序: 12 下沉到剩余元素末尾

{4, 5, 11, 2, 1, 12, 14, 19}

第 3 趟扫描排序: 11 下沉到剩余元素末尾

{4, 5, 2, 1, 11, 12, 14, 19}

第 4 趟扫描排序: 5 下沉到剩余元素末尾

{4, 2, 1, 5, 11, 12, 14, 19}

第 5 趟扫描排序: 4 下沉到剩余元素末尾
{2, 1, 4, 5, 11, 12, 14, 19}

第 6 趟扫描排序: 2 下沉到剩余元素末尾
{1, 2, 4, 5, 11, 12, 14, 19}

第 7 趟扫描排序: 空扫描,并没有元素交换
{1, 2, 4, 5, 11, 12, 14, 19}

冒泡排序的Java代码实现

	public static void bubbleSort(int[] arr) {
        int temp;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j + 1] < arr[j]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

冒泡排序的第一次优化

冒泡排序弊端

从上面的结果中我们能看出。
上面的算法实现有弊端,假设我给定一个有序数组进行冒泡排序,这个算法还是会给我排序 N -1趟,每一趟都进行空扫描。
那么有木有方法让元素已经排序好了,没有交换就不进行扫描,直接结束排序呢?
有的。只要在上面算法中动一点小手脚就好。
关键点:只要没有发生元素交换。就直接结束循环扫描。

冒泡排序第一版优化

	/**
     * 冒泡排序优化 1
     * @param arr 数组
     */
    public static void bubbleSortPro1(int[] arr) {
        int temp;
        // 记录每一趟排序是不是有元素交换
        boolean hasChange;
        for (int i = 0; i < arr.length - 1; i++) {
            hasChange = false;
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j + 1] < arr[j]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    // 如果有元素交换就记录下来
                    hasChange = true;
                }
            }
            // 只要某一趟排序完了没有元素交换,那么就结束。
            if (!hasChange) {
                break;
            }
        }
    }

冒泡排序第二次优化

假设有下面一个数组
{3, 4, 2, 1, 5, 6, 7, 8}
第一次扫描:
{3 ,2, 1, 4, 5, 6, 7, 8 }
第二次扫描:
{2 ,1, 3, 4, 5, 6, 7, 8 }
第三次扫描:
{1, 2, 3, 4, 5, 6, 7, 8 }
有木有发现一个问题,其实未排序的5,6,7,8(右侧已经有序),但是就算通过第二版优化,减少了扫描次数,那么每一套扫面描还是会让相邻的两个元素进行比较。
那么优化方案是啥:
关键点:记住最后一次交换的位置。下一次扫描只比较到这个位置。往后的元素不再比较。

冒泡排序第二版优化

	/**
     * 冒泡排序优化版2
     *
     * @param arr 数组
     */
    public static void bubbleSortPro2(int[] arr) {
        int tmp;
        boolean haschange;
        int sortBorder = arr.length - 1;
        int lastChangeIndex = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            haschange = false;
            for (int j = 0; j < sortBorder; j++) {
                if (arr[j] > arr[j + 1]) {
                    tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    haschange = true;
                    lastChangeIndex = j;
                }
            }
            sortBorder = lastChangeIndex;
            if (!haschange) {
                break;
            }
        }
    }

以上是关于给自己五分钟,彻底搞懂并优化冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章

给自己五分钟,彻底搞懂并优化冒泡排序

五分钟搞懂Vuex

五分钟搞懂Vuex

如何给面试官写一个满意的冒泡排序

卧槽!冒泡排序有这么难???

两分钟真能搞懂桶排序