七大经典排序算法——冒泡排序

文章目录


📑冒泡排序介绍

冒泡排序是一种简单但效率较低的排序算法。它重复地比较相邻的两个元素,如果顺序不对则交换它们,直到所有元素都被比较过一次。这样每一轮比较过后,最大的元素就会"冒泡"到最后面。接着,算法将会忽略最后一个元素,重复上述比较和交换的过程,直到所有元素都按照顺序排列。

⭐ 冒泡排序算法的步骤如下:

  1. 从数组的第一个元素开始,依次比较相邻的两个元素。
  2. 如果前一个元素大于后一个元素,交换它们的位置。
  3. 继续比较下一对相邻元素,直到最后一个元素。
  4. 重复以上步骤,每一轮比较都会将最大的元素"冒泡"到最后面。
  5. 当比较结束时,此时数组已经排好序,排序结束。

动图演示如下:

🌤️代码实现

🌳C语言版

c 复制代码
// 交换函数,用于交换数组中两个元素的位置
void swap(int* arr, int i, int j) {
    int tmp = arr[i];  // 将第一个元素的值存储在临时变量 tmp 中
    arr[i] = arr[j];   // 将第二个元素的值赋给第一个元素的位置
    arr[j] = tmp;      // 将临时变量 tmp 的值赋给第二个元素的位置
}

// 冒泡排序函数,用于对数组进行排序
void bobbleSort(int* arr, int n) {
    // 外层循环控制需要遍历的轮数,共进行 n-1 次遍历
    for (int i = 0; i < n - 1; i++) {
        // 内层循环进行相邻元素的比较和交换
        // j 的范围是从 0 到 n-i-1,这样每次内层循环可以比较并将最大值移动到最后
        for (int j = 0; j < n - i - 1; j++) { // j 进循环的条件容易出错,特殊标记下
            // 如果前一个元素比后一个元素大,交换它们
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);  // 调用交换函数进行交换
            }
        }
    }
}

🌳java版

java 复制代码
// 交换函数,用于交换数组中两个元素的位置
private static void swap(int[] array, int i, int j) {
    int tmp = array[i]; // 将第一个元素的值存储在临时变量 tmp 中
    array[i] = array[j]; // 将第二个元素的值赋给第一个元素的位置
    array[j] = tmp; // 将临时变量 tmp 的值赋给第二个元素的位置
}

// 冒泡排序函数,用于对数组进行排序
public static void bubbleSort(int[] array) {
    // 外层循环控制需要遍历的轮数
    for (int i = 0; i < array.length; i++) {
        // 内层循环进行相邻元素的比较和交换
        for (int j = i + 1; j < array.length; j++) {
            // 如果前一个元素比后一个元素大,交换它们
            if (array[i] > array[j]) {
                swap(array, i, j); // 调用交换函数进行交换
            }
        }
    }
}

🌤️做个简单的优化

可以在内层循环中定义一个变量 flag:用于检测这一轮内层循环是否发生了交换。初始值设为 1。

如果在一轮内层循环中没有发生交换(flag 仍为 1),说明数组已经有序,跳出循环即可。

🌳C语言版

c 复制代码
// 交换函数,用于交换数组中两个元素的位置
void swap(int* arr, int i, int j) {
    int tmp = arr[i];  // 将第一个元素的值存储在临时变量 tmp 中
    arr[i] = arr[j];   // 将第二个元素的值赋给第一个元素的位置
    arr[j] = tmp;      // 将临时变量 tmp 的值赋给第二个元素的位置
}

// 冒泡排序函数,用于对数组进行排序
void bobbleSort(int* arr, int n) {
    // 外层循环控制需要遍历的轮数,共进行 n-1 次遍历
    for (int i = 0; i < n - 1; i++) {
        int flag = 1; // 标记用于检测这一轮是否发生了交换
        // 内层循环进行相邻元素的比较和交换
        // j 的范围是从 0 到 n-i-1,这样每次内层循环可以比较并将最大值移动到最后
        for (int j = 0; j < n - i - 1; j++) { // j 进循环的条件容易出错,特殊标记下
            // 如果前一个元素比后一个元素大,交换它们
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1); // 调用交换函数进行交换
                flag = 0; // 发生交换后,将标记设置为 0
            }
        }
        // 如果没有发生交换,说明数组已经有序,提前退出排序
        if (flag) {
            break;
        }
    }
}

🌳java版

java 复制代码
// 交换函数,用于交换数组中两个元素的位置
private static void swap(int[] array, int i, int j) {
    int tmp = array[i];  // 将第一个元素的值存储在临时变量 tmp 中
    array[i] = array[j]; // 将第二个元素的值赋给第一个元素的位置
    array[j] = tmp;      // 将临时变量 tmp 的值赋给第二个元素的位置
}

public static void bubbleSort(int[] array) {
    // 外层循环控制需要遍历的轮数,共进行 array.length 次遍历
    for (int i = 0; i < array.length; i++) {
        boolean flg = true; // 标记用于检测这一轮是否发生了交换
        // 内层循环进行相邻元素的比较和交换
        // j 的范围是从 i+1 到 array.length,注意这里的起始点是 i+1
        for (int j = i + 1; j < array.length; j++) {
            // 如果前一个元素比后一个元素大,交换它们
            if (array[i] > array[j]) {
                swap(array, i, j); // 调用交换函数进行交换
                flg = false; // 发生交换后,将标记设置为 false
            }
        }
        // 如果没有发生交换,说明数组已经有序,提前退出排序
        if (flg) {
            break;
        }
    }
}

🌤️复杂度和稳定性分析

时间复杂度分析:在最坏的情况下,冒泡排序需要进行n-1轮比较,每轮比较需要进行n-i次。因此,总的比较次数为(n-1) + (n-2) + ... + 2 + 1 = n(n-1)/2,近似为O(n^2^)。

空间复杂度分析:使用了常数个变量,因此空间复杂度为O(1)

什么是稳定性?

答:稳定性指的是相同的数据所在的位置经过排序后是否发生变化。换句话说就是大小相同的两个值在排序之前和排序之后的先后顺序不变,这就是稳定的。

稳定性分析:冒泡排序将小的元素往前调或者把大的元素往后调;比较的是相邻的两个元素,交换也发生在这两个元素之间;因为相等的元素不会进行交换,所以稳定。

总结: 冒泡排序的时间复杂度为O(N^2^),空间复杂度为O(1),而且是稳定的排序。


☁️结语

请给自己些耐心,不要急于求成。
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!


都看到这里啦!真棒(*^▽^*)

可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家

如有纰漏或错误,欢迎指正


相关推荐
武子康8 分钟前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
Captain823Jack42 分钟前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
豪宇刘1 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意1 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
Captain823Jack1 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词
是小胡嘛2 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_748255022 小时前
前端常用算法集合
前端·算法
FF在路上2 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进2 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
呆呆的猫2 小时前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展