排序算法(一)-冒泡排序

0. 原理

  • 临近的数字两两比较,按照从小到大或者从大到小的顺序进行交换。
  • 每一趟会将最大或者最小的数字放到最终结果的位置
  • 重复操作直到倒数第二位

对[2, 8, 1, 5, 3]这个数组排序,完整流程如下

round 1 start
2 8 1 5 3  (exchange data: 3 <-> 5)  2 8 1 3 5 
2 8 1 3 5  (exchange data: 1 <-> 8)  2 1 8 3 5 
2 1 8 3 5  (exchange data: 1 <-> 2)  1 2 8 3 5 
round 1 finish
round 2 start
1 2 8 3 5  (exchange data: 3 <-> 8)  1 2 3 8 5 
round 2 finish
round 3 start
1 2 3 8 5  (exchange data: 5 <-> 8)  1 2 3 5 8 
round 3 finish
round 4 start
round 4 finish

可见第一趟将最小的1放到了第一位
为什么叫冒泡排序呢?因为上面两两交换的过程每一趟都将最小的值放到了最顶端,很像气泡上升到顶部的过程。

1. 实现

关键代码实现如下:

@Override
public int[] sort(int[] data) {
    if (data == null || data.length <= 1) {
        return data;
    }

    for (int i = 0; i < data.length - 1; i++) {
        for (int j = data.length - 1; j > i; j--) {
            if (data[j] < data[j - 1]) {
                swap(data, j, j - 1);
            }
        }
    }

    return data;
}

具体实现可查看:

GitHub/BubleSort.java

2. 复杂度分析

从代码和原理可以看出,外层循环需要n-1次,内层循环需要n-i次,比较一次,数据操作三次。因此最坏的情况应该是整个序列时逆向的,时间复杂度为O(n²),最好的情况是序列时正序的一次扫描即可,时间复杂度为O(n)。平均时间复杂度为O(n²)。由于不需要额外空间,空间复杂度为O(1)

3. 优化

3.1 优化点一

如果某一趟没有发生过一次交换,则说明该数组已经有序,可以直接停止循环。只要加一个标识变量就可以实现。

3.2 优化点二

使用一个标识变量记录下最后一个发生交换的位置,则可以说明前面没有发生交换的序列已经有序,所以内部循环的终结点可以用这个值来作为结束点,也就是上面代码中的i值。在内部循环结束后i=changFlag就是这个作用。

两个优化点写入代码后如下:

@Override
public int[] sort(int[] data) {
    if (data == null || data.length <= 1) {
        return data;
    }

    //标识是否已经有序
    boolean isChanged;
    //标识最后一个发生变化的位置
    int changFlag = 0;

    for (int i = 0; i < data.length - 1; i++) {
        isChanged = false;
        System.out.println("round " + (i + 1) + " start");
        for (int j = data.length - 1; j > i; j--) {
            if (data[j] < data[j - 1]) {
                swap(data, j, j - 1);
                isChanged = true;
                changFlag = j - 1;
            }
        }
        //i直接设置为最后一次的交换
        i = changFlag;
        //如果没有改变,则证明序列已经有序
        if (!isChanged) {
            System.out.println("no exchange, break out loop");
            break;
        }
        System.out.println("round " + (i + 1) + " finish");
    }

    return data;
}

具体实现可查看:

GitHub/BubleSort.java

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值