排序算法:冒泡排序

文章目录

一、简介

冒泡排序(Bubble Sort)是一种简单直观的排序算法。通过对要排序的数组从前向后循环遍历,依次对相邻两个元素的值进行比较,如果他们的顺序错误就把他们交换过来。一直重复执行,直到没有元素交换,也就代表该数组已经排序完成了。这个算法的名字由来是因为越小的元素会经由交换慢慢的到数组的最前面。

作为最简单的排序算法之一,冒泡排序还有一种优化手段,就是创建一个布尔变量,用于判断当前循环是否发送了交换,如果遍历中元素没有发生交换,则证明该数组已经有序。但这种改进对于提升性能来说并没有什么太大作用。

二、动图演示


三、代码实现

3.1 原始版本

java 复制代码
import java.util.Arrays;

public class Sort {

    public static void main(String[] args) {
        // 排序前的数组
        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
        System.out.println("排序前:" + Arrays.toString(arr));

        // 调用冒泡排序方法
        bubbleSort(arr);

        // 排序后的数组
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    // 冒泡排序
    public static void bubbleSort(int[] arr) {

        // 每次排序都会冒出一个最大值,如果有 n 个数据,则要进行 n - 1 次排序
        // 当你进行第 n - 1 次循环,剩下的那个数据必然是符合要求的,就没必要进行排序,所以可以 -1
        for (int i = 0; i < arr.length - 1; i++) {

            // 这里要 -i 的原因是,当每次外层循环结束后,都会产生一个最大值
            // 所以在后面的内层循环就没必要再对这个最大值进行比较,没意义
            for (int j = 0; j < arr.length - 1 - i; j++) {

                // 核心逻辑:如果当前元素大于后一个元素,则交换,最终达到从小到大排序
                // 反之:如果当前元素小于后一个元素,再=在交换的话,最终会达到从大到小排序
                if (arr[j] > arr[j + 1]) {

                    // 交换规则:让当前元素变成后一个元素,后一个元素变成当前元素
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

运行结果:

java 复制代码
排序前:[3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
排序后:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

3.2 优化版本

试想一下,如果排序的数组在某一轮排序中没有元素交换,这就说明这个数组已经有序了,则可以提前结束排序,避免不必要操作。

优化步骤:

  • 引入 swapped 布尔变量,用于标记每一轮排序是否发生了元素交换。
  • 在内层循环中,如果有元素交换,将 swapped 设为 true。
  • 在内层循环结束后,如果 swapped 为 false,说明数组已经有序,提前结束排序。
java 复制代码
import java.util.Arrays;

public class Sort {

    public static void main(String[] args) {
        // 排序前的数组
        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
        System.out.println("排序前:" + Arrays.toString(arr));

        // 调用冒泡排序方法
        bubbleSort(arr);

        // 排序后的数组
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    // 冒泡排序
    public static void bubbleSort(int[] arr) {
    
        // 用于标记是否发生交换
        boolean swapped;

        // 每次排序都会冒出一个最大值,如果有 n 个数据,则要进行 n - 1 次排序
        // 当你进行第 n - 1 次循环,剩下的那个数据必然是符合要求的,就没必要进行排序,所以可以 -1
        for (int i = 0; i < arr.length - 1; i++) {

            // 没有交换
            swapped = true;

            // 这里要 -i 的原因是,当每次外层循环结束后,都会产生一个最大值
            // 所以在后面的内层循环就没必要再对这个最大值进行比较,没意义
            for (int j = 0; j < arr.length - 1 - i; j++) {

                // 核心逻辑:如果当前元素大于后一个元素,则交换,最终达到从小到大排序
                // 反之:如果当前元素小于后一个元素,再=在交换的话,最终会达到从大到小排序
                if (arr[j] > arr[j + 1]) {

                    // 交换规则:让当前元素变成后一个元素,后一个元素变成当前元素
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;

                    // 发生交换
                    swapped = false;
                }
            }

            // 如果没有发生交换,则代表当前数组已经有序了,可以中断外层循环,减少循环次数,提高效率
            if (swapped) {
                break;
            }
        }
    }
}

运行结果:

java 复制代码
排序前:[3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
排序后:[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

3.3 性能比较

我通过定义一个 count 变量,得到两个版本完成排序后的的循环次数,用于统计两个版本冒泡排序的性能,结果如下:

  • 原始版本:105 次
  • 优化版本:95 次

原始冒泡排序和优化后的冒泡排序在最坏和平均情况下的时间复杂度都是 O(n^2),但优化后的冒泡排序在最好情况下(即数组已经有序)可以提前终止,将时间复杂度降至 O(n),提高了在部分有序数组排序时的性能。

在空间复杂度方面,二者都为 O(1),因为只使用了少量辅助变量,不需要额外空间存储元素。


四、总结

冒泡排序并非是很高效的排序算法,冒泡排序主要适用于小数据量排序,在实际应用中使用的比较少,更多可能会出现在考试和简单的笔试中。要求掌握其两个版本的实现和知道其时间复杂度,这样有助于理解排序算法的基本原理。


相关推荐
SsummerC10 分钟前
【leetcode100】二叉树的直径
数据结构·python·算法·leetcode
奔跑de自由25 分钟前
解锁 C 语言字符函数密码,开启高效编程之路
c语言·开发语言·算法
EviaHp25 分钟前
递归构建树菜单节点
java·spring boot·后端·maven·idea
HappyAcmen41 分钟前
关于Java适配器模式的面试题目及其答案
java·面试·适配器模式
love静思冥想42 分钟前
自动化执行 SQL 脚本解决方案
java·数据库·sql·自动化
Miraitowa_cheems1 小时前
【JavaEE】Spring Web MVC
java·spring boot·java-ee
要努力学习ψ(`∇´)ψ1 小时前
红黑树详解
开发语言·数据结构·c++
iamlzjoco1 小时前
idea报错Malformed \uxxxx encoding.报错解决
java·ide·intellij-idea
华年源码2 小时前
基于SpringBoot的旅游网站的设计与实现(源码+数据库+文档)
java·毕业设计·源码·springboot·旅游
北京_宏哥2 小时前
《手把手教你》系列技巧篇(十九)-java+ selenium自动化测试-元素定位大法之By css下卷(详细教程) 1.简介
java·selenium·前端框架