十大经典排序算法之冒泡排序(Java语言)附带三种优化方式

理论

冒泡排序也是入门学的最简单的排序算法之一,顾名思义,这个排序算法的思想呢就是每次都把最大的泡泡(数字)浮到最顶端去,然后再从后面把第二大的数向上浮,直到只剩最后一个泡泡了
实际的操作过程:
是将指针不断向后移动,并且对比相邻的两个数字,如果前面的大就交换位置,如果后面的大就不交换位置,不管是不是交换位置,之后都要将指针继续向上移动,然后再次对比
比如有如下数组
3,1,5,4,2
第一次循环
指针在第0个位置:1,3,5,4,2 因为3>1,交换
指针在第1个位置:1,3,5,4,2 因为3<5,不交换
指针在第2个位置:1,3,4,5,2 因为5>4,交换
指针在第3个位置:1,3,4,2,5 因为5>2,交换
至此第一次循环完成,再进行下一轮循环,因为最大的数已经冒到最上面了,所以下一次循环只需要指针只需要到第2个位置就可以了
每次循环都会将剩下的待排数组里面最大的数字冒到最上面来,最后会变成有序数组

性质

中文名称英文名称平均时间复杂度最坏时间复杂度最好时间复杂度空间复杂度稳定性
冒泡排序Bubblen2n2n1稳定

最简单实现

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

优化

但是这种写法呢,无论如何时间复杂度都是n2,所以还要加一点优化进来,让其最好时间复杂度能达到O(n)
1、首先加个标记,假设待排数组本来就是有序的,那么一轮冒泡下来,我们就可以确定不再需要下一轮冒泡了,所以可以加上标记来记录是否有交换发生
2、假设数组后半部分的数都在正确的位置,那么,每次循环我们就不再需要从后半部分来循环了,所以我们可以加一个标记,来记录我们发生替换的最高位置,下次循环不再遍历记录的最高位后面的部分
3、假设数组中间部分的元素都在正确的位置,志愿后最大值和最小值反了,按照原本的逻辑,最大值拍到最上面去了,那最小值移动到最下面的话还要循环n-2次,那么我们可不可以直接反向冒泡将最小值到最低端呢,当饭是可以的,就在一次循环除了正向冒泡后再加一次反向冒泡,那么相当于两冒泡便可以将数组排好序

其实用了第一种方式后最好的时间复杂度已经是O(n)了,但是我们不能止步于此,于是有了2和3
上代码

public static void sort2(int arr[]){
    int high = arr.length - 1;//记录正向遍历的最大索引位置
    int low = 1;//记录反向遍历的最小索引位置
    for (int i = 1; i < arr.length; i++) {
        boolean flag = true;
        int pos = 0;
        for (int j = 0; j < high; j++) {
            if(arr[j] > arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                flag = false;//记录是否发生过交换
                pos = j;//记录当前比较到的最高位
            }
        }
        if(flag){
            return;
        }
        high = pos;
        //反向遍历,记录反向的index最小值
        flag = true;
        for (int j = high; j > low; j--){
            if(arr[j] < arr[j-1]){
                int temp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = temp;
                flag = false;
                i = j;
            }
        }
        low = i;
        if(flag){
            return;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值