冒泡排序的优化

本文详细介绍了冒泡排序的基本原理,并通过实例展示了冒泡排序的原始实现。针对无用功问题,提出了两种优化策略:一是通过设置标志位`isPristine`来提前结束循环,二是记录最后发生交换的位置作为无序区边界。这两种优化有效地减少了不必要的比较和交换操作,提高了排序效率。
摘要由CSDN通过智能技术生成

总结:冒泡排序就是利用双层for循环,外层循环控制轮数,内层循环负责把数组内的数字两两比较,较大的数放到后一个位置上去。

第一次外层循环后,就能得到最大的数并且放在了数组最后一个位置。

第二次外层循环后,得到第二大的数放在倒数第二位上。

.

.

.

以此类推

int[] array = {5, 4, 6, 3, 4, 8, 77};
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]){
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }

补充知识点:在IDEA中像 j 循环中的交换 ,可以把代码片段选中,右键选中Refactor再选中Extract Method 就可以自动生成一个函数并调用。如下图: 思考:对于数组 {2,1,3,4,5,6}来说上面的冒泡排序存在的问题?

循环i = 0 j = 0以后数组就变成了 {1,2,3,4,5,6}

但是程序不会结束,只会傻傻的继续跑,但其实以及是最终结果了后面都是做的无用功。

如何避免上诉问题对冒泡排序进行优化?

在每一次i循环开始时定义一个boolean isPristine 默认为true,代表没有数组保持原样。如果发生改变即有交换操作就令isPristine改成false,代表数组不是原来的样子。在每一次i循环的最后判断,如果数组没有发生改变,表示数组已经是最终状态,退出循环即可。

优化代码如下:

int[] array = {2,1,3,4,5,6};
        for (int i = 0; i < array.length - 1; i++) {
            boolean isPristine = true;
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]){
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    isPristine = false;
                }
            }
            if (isPristine){
                break;
            }
        }
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }

思考:对于数组 {3,4,2,1,5,6,7,8}来说上面的冒泡排序存在的问题?

第一轮

3 4 比,位置不变

4 2 比,交换位置 数组变成 {3,2,4,1,5,6,7,8}

4 1 比,交换位置 数组变成 {3,2,1,4,5,6,7,8}

45比,位置不变

56比,位置不变

67比,位置不变

78比,位置不变

第一轮确定了最后一个位置的数8 数组变成{3,2,1,4,5,6,7,8}

第二轮

32比,交换位置 数组变成 {2,3,1,4,5,6,7,8}

31比,交换位置 数组变成{2,1,3,4,5,6,7,8}

后半段都是有序的了但是程序仍然会继续傻傻的跑下去

如何解决这种问题?

上面的冒泡排序的有序区间只跟轮数有关,第1轮结束后,确定了一个最大的数放在最后面,有序区间的长度为1,第二轮结束后为2,但实际上真正的有序区间可能大于这个数字。

如何避免这种情况?

在每一轮的排序后面记录一下最后发生交换的位置,作为无序数列的边界,再往后就是有序数列了。

代码如下:

 int[] array = {5, 4, 6, 3, 4, 8, 77};
        int border = array.length - 1;
        int lastChangedIndex = 0;
        for (int i = 0; i < array.length - 1; i++) {
            boolean isPristine = true;
            for (int j = 0; j < border; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    isPristine = false;
                    lastChangedIndex =j;
                }
            }
            border =lastChangedIndex;
            if (isPristine) {
                break;
            }
        }
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值