今日算法解读之冒泡排序(bubble sort)

8 篇文章 0 订阅

📕 算法介绍

冒泡排序是计算机科学领域比较简单的排序算法之一,因此也成为了java、Python、C++等各大编程语言算法入门必修之课。

维基百科说:冒泡排序对于数据量很大的集合排序来说效率会降低地很明显,反之其他算法比如插入排序对于同场景则更高效。 但作为编程语言初学者,掌握算法的概念和逻辑,冒泡排序足矣。

时间复杂度:冒泡排序的时间复杂度最坏情况是O(n²),平均时间复杂度是O(n²),最优的时间复杂度是O(n)。

冒泡排序名词由来:泡泡在浮出水面之前会被挤压显得很小,因此泡泡可以想象成集合中的元素。元素会经由比较与交换最终按照排序规则,如果是升序,则比值大的元素会排在最右端,反之会排在最左端。那泡泡呢,会在水里互相排挤,大的泡泡浮力大则最先浮出水面,以此类推。泡泡互相挤压并因浮力大小交错位置的行为可以理解为元素的比较与交换,泡泡全部浮出水面可以理解为算法排序结束。

📑 算法分析

例图

冒泡排序就是将上图的列表按照从大到小 (Ascending) 或 从小到大 (Descending) 顺序进行排序的一个过程。其中每一对 Array[i]、Array[i + 1],且 i < n - 1,作为一个比较单元,最终根据升降序规则进行元素交换。比如上图的 4 与 3、3 与 5 等等,都属于一个比较单元。

由于每一个列表中,都存在一个最大值或最小值,根据式子

A > B...Y > Z

可以推出,无论 A、B 或 C 处于什么顺序,A 和 Z 作为边界总是会最先被推到列表一端。那么确认最大值的时间复杂度,最坏为 O(n)。当 Array[0] = Max 时,即可证明。那么次于最大值的元素

 Y,被排序后应该处于 Array[n - 2] 的位置,而相应的,X 应处于 Array[n - 3] 的位置。由于每一轮总是能确定 Array[n - i] 的位置,因此作为 j 的边界可以控制在 n - i 以内。

 

 上图可以体会一下,第一轮排序后

3,4,5,5,2,4,2,6,8

即便 6 不在 n - 2 的位置,而在其它更靠前的位置,那么你可以想象从 4 向右推,最终也还是把 6 推向 n - 2 的位置,而 8 大于它,因此不会交换,结束本轮排序。 

🖊 代码实现

for 循环版本

    public void sort(int[] nums) {
        int N = nums.length;
        int tmp = 0;
        for (int i = 0; i < N; i++) {
            // N - 1 是为 j + 1 预留空间避免数组越界
            // N - i 就是上面讲的控制 j 的边界
            for(int j = 0; j < N - i - 1; j++) {
                if(nums[j] > nums[j + 1]) {
                    // 元素交换
                    tmp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = tmp;
                }
            }
        }
    }

while 循环版本

 public static <T> void bubbleSort(T[] t, Comparator com, int right) {
        // no need to sort if array's length equals to 1 or 0
        if (right == 1 || right == 0)
            return;
        // both while and nested for looping are alright, it depends on your work requirement
        while (true) {
            // the var index represents the outer looping
            int index = 0, edgeIndex = 0;
            T temp;
            for (int i = 1; i < right; i++) {
                if (com.compare(t[i], t[index]) < 0) {
                    // swapping
                    temp = t[i];
                    t[i] = t[index];
                    t[index] = temp;
                    edgeIndex = i;
                }
                index++;
            }
            right = edgeIndex;
            System.out.println(Arrays.toString(t));
            if (right == 0) {
                break;
            }
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿码叔叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值