【Java-算法】-冒泡排序

4 篇文章 0 订阅
4 篇文章 0 订阅
1.什么冒泡排序

冒泡排序是通过相邻2个元素比较,依次找到当次循环最大值放到右边,通过当前数组(length-1)次外围循环比较,得出最终的有序数组。

2.冒泡排序常见方式
  • 下面普通的冒泡排序方式:通过内层冒泡比较当前最大值和(length-1)比较次数
    /**
     * 冒泡排序,相邻比较,最大的右移
     * 常见版本
     *
     * @param arr
     */
    public static void bubbleSort_1(int[] arr) {
        //比较次数length-1次
        for (int i = 0; i < arr.length - 1; i++) {
            //单词冒泡:比较相邻2个数值大小,大的右移动
            for (int j = 0; j < arr.length - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }
            System.out.printf("bobbleSort_1 ==> arr:" + Arrays.toString(arr) + "\n\r");
        }
    }

打印输出

bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 4, 5, 7, 3, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 4, 5, 3, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 4, 3, 5, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]
bobbleSort_1 ==> 冒泡内循环比较次数:0
bobbleSort_1 ==> 冒泡内循环比较次数:1
bobbleSort_1 ==> 冒泡内循环比较次数:2
bobbleSort_1 ==> 冒泡内循环比较次数:3
bobbleSort_1 ==> 冒泡内循环比较次数:4
bobbleSort_1 ==> 冒泡内循环比较次数:5
bobbleSort_1 ==> 冒泡内循环比较次数:6
bobbleSort_1 ==> 冒泡内循环比较次数:7
bobbleSort_1 ==> arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]

可以看出来不管数组是否已经排序完成,都需要循环(length-1)次,比较浪费时间。

  • 根据上面方式优化的版本:优化外层循环的次数,当其中内循环未交换元素,说明当前数据已经是有序的
    /**
     * 冒泡排序,相邻比较,最大的右移
     * 优化版本-当其中一次没有比较交换时,说明已经完成排序了
     *
     * @param arr
     */
    public static void bubbleSort_2(int[] arr) {
        //比较次数length-1次
        for (int i = 0; i < arr.length - 1; i++) {
            Boolean isSwap = false; //是否发生比较交换元素
            //每次右移找到最大值,所以比较次数相对应该减少i
            for (int j = 0; j < arr.length - 1 - i; j++) {
                System.out.printf("bubbleSort_2 ==> 冒泡内循环比较次数:" + j + "\n\r");
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                    isSwap = true;
                }
            }
            System.out.printf("bubbleSort_2 ==>第" + i + "次比较, arr:" + Arrays.toString(arr) + "\n\r");
            //当其中一次没有比较交换时,说明已经完成排序了
            if (!isSwap) {
                break;
            }
        }
    }

打印输出

bubbleSort_2 ==> 冒泡内循环比较次数:0
bubbleSort_2 ==> 冒泡内循环比较次数:1
bubbleSort_2 ==> 冒泡内循环比较次数:2
bubbleSort_2 ==> 冒泡内循环比较次数:3
bubbleSort_2 ==> 冒泡内循环比较次数:4
bubbleSort_2 ==> 冒泡内循环比较次数:5
bubbleSort_2 ==> 冒泡内循环比较次数:6
bubbleSort_2 ==> 冒泡内循环比较次数:7
bubbleSort_2 ==>第0次比较, arr:[1, 2, 4, 5, 7, 3, 9, 10, 21]
bubbleSort_2 ==> 冒泡内循环比较次数:0
bubbleSort_2 ==> 冒泡内循环比较次数:1
bubbleSort_2 ==> 冒泡内循环比较次数:2
bubbleSort_2 ==> 冒泡内循环比较次数:3
bubbleSort_2 ==> 冒泡内循环比较次数:4
bubbleSort_2 ==> 冒泡内循环比较次数:5
bubbleSort_2 ==> 冒泡内循环比较次数:6
bubbleSort_2 ==>第1次比较, arr:[1, 2, 4, 5, 3, 7, 9, 10, 21]
bubbleSort_2 ==> 冒泡内循环比较次数:0
bubbleSort_2 ==> 冒泡内循环比较次数:1
bubbleSort_2 ==> 冒泡内循环比较次数:2
bubbleSort_2 ==> 冒泡内循环比较次数:3
bubbleSort_2 ==> 冒泡内循环比较次数:4
bubbleSort_2 ==> 冒泡内循环比较次数:5
bubbleSort_2 ==>第2次比较, arr:[1, 2, 4, 3, 5, 7, 9, 10, 21]
bubbleSort_2 ==> 冒泡内循环比较次数:0
bubbleSort_2 ==> 冒泡内循环比较次数:1
bubbleSort_2 ==> 冒泡内循环比较次数:2
bubbleSort_2 ==> 冒泡内循环比较次数:3
bubbleSort_2 ==> 冒泡内循环比较次数:4
bubbleSort_2 ==>第3次比较, arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]
bubbleSort_2 ==> 冒泡内循环比较次数:0
bubbleSort_2 ==> 冒泡内循环比较次数:1
bubbleSort_2 ==> 冒泡内循环比较次数:2
bubbleSort_2 ==> 冒泡内循环比较次数:3
bubbleSort_2 ==>第4次比较, arr:[1, 2, 3, 4, 5, 7, 9, 10, 21]

从日志中可以看出,明显的外层循环次数少了,因为在第5次比较完成后,数组已经是有序得了,第六为了进行比对交换,所以直接bredk。

  • 最终优化方案:1.减少内层比较次数,最后一次交换位置和后面已经完成排序,后续不需要在进行比较交换
 /**
     * 冒泡排序,相邻比较,最大的右移
     * 最终优化版本-1.减少内层比较次数,最后一次交换位置和后面已经完成排序,后续不需要在进行比较交换
     *
     * @param arr
     */
    public static void bubbleSort_3(int[] arr) {
        //比较次数
        int n = arr.length - 1;
        while (true) {
            int last = 0; //最后一次交换的位置
            //每次右移找到最大值,记录最后一次交换的左边位置,表示 j~length 已经完成排序
            for (int j = 0; j < n; j++) {
                System.out.printf("bubbleSort_3 ==> 冒泡内循环比较次数:" + j + "\n\r");
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                    //如果最后一次交换的是index =0,则标识已经完成排序
                    last = j;
                }
            }
            n = last;
            System.out.printf("bubbleSort_3 ==>比较, arr:" + Arrays.toString(arr) + "\n\r");
            //如果最后一次交换的是index =0,则标识已经完成排序
            if (n == 0) {
                break;
            }
        }
    }

每次的比对最后一次的比对位置和其后面的last位置元素都已经按照顺序排列,只需要进行 index < last位置的元素比对交换,直到最后一次比对位置last==0,说明已经是最小元素,跳出循环,由于直接使用last来较少循环次数,没有使用到外层训循环,直接可以用while(true)替换,更加美观方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值