冒泡排序浅析

冒泡排序的定义:

针对一个含有n个元素的数组,共进行n-1轮操作,每轮操作当前剩余元素的最大元素冒泡到数组末尾,每轮操作的具体过程为,对剩余元素从0开始两两比较并交换。

冒泡排序Java代码实现:

基础实现方式:

//冒泡排序基础版
    private static void bubbleSort0() {
        int[] arr = {1, 0, -3, 4, 6, -1, 8, 2, 9, 10};//共10个元素
        System.out.println("排序前: " + Arrays.toString(arr));
        for (int i = 1; i < arr.length; i++) {//共需要9轮操作,每轮操作确定一个当前最大元素,确定了9个即完成
            for (int j = 0; j < arr.length - i; j++) {//从头开始,两两比较,确定剩余元素中最大元素
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println("排序后: " + Arrays.toString(arr));
    }

考虑到一种极端情况,给定的原始数组已经是有序数组了,如[-3, -1, 0, 1, 2, 4, 6, 8, 9, 10],在这种情况下,一轮操作都不需要,前面基础实现中,总共需要n-1轮的操作,考虑到有可能进行了小于n-1轮的操作后,数组已经有序了,那么n-1轮中剩余轮操作就不需要了,代码优化如下:

//冒泡排序优化一:轮数优化,针对进行到第n轮的时候已经是有序数组了,剩余轮数就没有必要比较了
    private static void bubbleSort1() {
        int[] arr = {-3, -1, 0, 1, 2, 4, 6, 8, 9, 10};//极端情况,给定的数组已经有序
        System.out.println("排序前: " + Arrays.toString(arr));
        for (int i = 1; i < arr.length; i++) {
            boolean isSorted = true;
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    isSorted = false;
                }
            }
            if (isSorted) {
                break;
            }
        }
        System.out.println("排序后: " + Arrays.toString(arr));
    }

前面的优化,针对的是轮数优化,说的是基础版本中总共需要n-1轮的操作,可能进行到比如说第3轮,第4轮,也就是进行到小于n-1轮的时候,数组已经有序了,那么n-1轮中剩余的轮数就不用操作了,另外一方面,还可以从每轮操作的范围进行优化,也即从无序边界的维度进行优化,基础版本中,无序边界 = n - 已确定元素,实际上无序边界可能比这种小,如数组[1, 0, -6, 3, 4, 5, 7, 8, 9, 10],实际上0,-6比较交换后,后面的元素已经是有序的了,无序再两两比较了,这种情况下代码优化如下:

//冒泡排序优化二:无序边界界定,即每轮操作可能并不需要对 n-已确定元素 个元素进行两两比较
    public static void bubbleSort2() {
        int[] arr = {1, 0, -6, 3, 4, 5, 7, 8, 9, 10};
        int sortBorderPos = arr.length - 1;
        int lastExchangePos = 0;
        System.out.println("排序前: " + Arrays.toString(arr));
        for (int i = 1; i < arr.length; i++) {
            boolean isSorted = true;
            for (int j = 0; j < sortBorderPos; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    isSorted = false;
                    lastExchangePos = j;
                }
            }
            sortBorderPos = lastExchangePos;
            if (isSorted) {
                break;
            }
        }
        System.out.println("排序后: " + Arrays.toString(arr));
    }

实际上这两种优化的本质是去除无效操作,并不能根本上减小冒泡排序的时间复杂度。说到时间复杂度,冒泡排序的时间复杂度如下:

最好时间复杂度:O(n),即给定数组已经是有序数组的情况下,只需要进行一轮操作,n个元素两两比较一轮即可,参考优化一。
最坏时间复杂度:O(nn),即给定数组为完全逆序数组,这种情况下,共需要进行n-1轮操作,每轮操作对剩余元素都需要两两比较并交换元素。
平均时间复杂度:O(n
n)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值