浅谈冒泡排序

冒泡排序只会操作相邻的两个数据,即比较交换。执行一次冒泡操作会至少让一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。
我们来举个例子,现在有一个数组,元素分别为5、1、4、3、2,第一次冒泡操作的详细过程如下图所示。
在这里插入图片描述
经过一次冒泡,5这个元素到了a[4]的位置。每次排序就好像水底的泡泡一样,大的泡泡逐渐往上冒,所以称之为冒泡排序。接下来只需要再进行4次冒泡操作就可以使整个数组的元素从小到大排好序了。

在实际的代码中,我们为了减少时间复杂度,可以考虑这样一种情况,当我们进行完一次冒泡操作之后,发现本次冒泡操作中没有元素交换,也就是说剩余的元素已经有序,因此剩下的元素我们没有必要进行冒泡操作了。

为了能够实现停止冒泡的操作,这里引入了一个标识符,用来表明本次冒泡是否发生了元素交换,代码如下:

//a表示要排序的数组,n表示数组的长度
    public void bubbleSort(int[] a , int n){
        if(n <= 1) return;
        //外循环固定本次冒泡的元素,内循环用本次冒泡的数与其它的数进行比较
        for(int i = 0 ; i < n ; i++){
            //定义一个标志用来表明本次冒泡是否发生过元素交换,初始值为false
            boolean flag = false;
            for(int j = 0 ; j < n-i-1;j++){
                //如果前一个元素比后一个元素大,交换
                if(a[j] > a[j+1]){
                    int tmp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = tmp;
                    //由于发生过交换了,标志改为true
                    flag = true;
                }
            }
            //本次冒泡结束后,如果没有发生交换,即flag还为false,则退出循环
            if(flag == false) return;
        }
        
    }

1.冒泡排序是原地排序算法吗?

因为冒泡排序中的交换只涉及到相邻的两个数据间的交换,是需要额外的常量级的临时空间即代码中的int tmp,用来临时存储需要交换的数据,所以空间复杂度为O(1),是一个原地的排序算法。

2.冒泡排序是稳定的排序算法吗?

我们可以看出,代码中交换的条件为前一个元素比后一个元素大,即a[j] > a[j+1] 所以如果两个元素相等并不会发生交换。所以冒泡排序是稳定的排序算法。

3.冒泡排序的时间复杂度是多少?

最好情况下,就是所有的元素已经有序,那么根据代码我们只需要进行一次外循环操作,就可以结束排序。一次外循环内会遍历一次整个数组,所以最好情况下的时间复杂度为O(n)。而最坏的情况,元素是按从大到小有序排列的,而我们需要的顺序是有小到大,这种情况最糟,我们需要n次外循环,n次内循环,那么时间复杂度就为O(n²)
知道了最好情况和最坏情况,那么平均情况该如何理解呢?这里要提出两个概念,有序度逆序度
有序度是指是指数组中具有有序关系的元素对的个数。有序元素对用数学表达式表示如下:

当a[i] < = a[j] 时,满足 i < j

上边的例子中,数组里的元素为5、1、4、3、2。
其中有序元素对为(1、4)、(1,3)、(1,2)
对于一个倒序排列的数组5、4、3、2、1,有序度为0,正序排列的数组1、2、3、4、5有序度为n*(n-1)/2 ,也就是10。我们把这种完全有序的数组的有序度叫做满有序度。而逆序度在这里就不过多的讲解,聪明的你一定可以举一反三的理解。

不管算法怎么改进,一个要排列的数组中的元素的逆序度总是固定的,所以需要交换的次数也是固定的。上述例子中的有序度为3,那么逆序度就为10-3=7。

对于一个数组最好情况下需要的交换次数为0,而最坏情况下需要交换的次数为n*(n-1)/2 ,我们去平局值,即n*(n-1)/4。简化过后,平均时间复杂度就为O(n²)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值