news 2026/4/25 19:25:42

深入浅出冒泡排序:原理、实现与优化(附C++代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入浅出冒泡排序:原理、实现与优化(附C++代码)

深入浅出冒泡排序:原理、实现与优化(附C++代码)

大家好!今天我们来聊聊排序算法里最基础也最经典的一种——冒泡排序。它的核心思想简单易懂,非常适合排序算法的入门学习。这篇文章会从原理拆解、过程演示、代码实现,再到优化方向,一步步带大家吃透冒泡排序,最后附上可直接运行的C++代码,方便大家实操练习。

一、什么是冒泡排序?

冒泡排序(Bubble Sort)是一种简单的交换排序算法,它的核心思路是:重复遍历要排序的数组,每次比较相邻的两个元素,如果它们的顺序错误就把它们交换过来。

为什么叫“冒泡”呢?因为在排序过程中,较大的元素会像水中的气泡一样,逐渐“上浮”到数组的末尾(或者较小的元素“下沉”到数组开头),每一轮遍历都会确定一个未排序部分的最大(或最小)元素的最终位置。

二、冒泡排序的核心原理与过程演示

1. 核心原理

冒泡排序的本质是通过相邻元素的多次比较与交换,将无序元素逐步“筛选”到正确位置。其基本步骤如下:

  • 从数组的第一个元素开始,依次比较相邻的两个元素(第i个和第i+1个);

  • 如果前者大于后者(升序排序),则交换这两个元素的位置;

  • 继续向后比较下一对相邻元素,直到遍历到数组的末尾;

  • 完成一轮遍历后,数组中最大的元素会被“冒泡”到数组的最后一位(这一位已排序完成,后续遍历无需再考虑);

  • 重复上述过程,每轮遍历排除已排序的末尾元素,直到整个数组有序。

2. 过程演示(以数组 [5, 3, 8, 4, 2] 升序排序为例)

初始数组:[5, 3, 8, 4, 2]

第1轮遍历(未排序范围:0~4):

  • 比较 5 和 3:5>3,交换 → [3, 5, 8, 4, 2]

  • 比较 5 和 8:5<8,不交换 → [3, 5, 8, 4, 2]

  • 比较 8 和 4:8>4,交换 → [3, 5, 4, 8, 2]

  • 比较 8 和 2:8>2,交换 → [3, 5, 4, 2, 8]

  • 结果:最大元素 8 冒泡到末尾,有序部分:[8]

第2轮遍历(未排序范围:0~3):

  • 比较 3 和 5:3<5,不交换 → [3, 5, 4, 2, 8]

  • 比较 5 和 4:5>4,交换 → [3, 4, 5, 2, 8]

  • 比较 5 和 2:5>2,交换 → [3, 4, 2, 5, 8]

  • 结果:第二大元素 5 冒泡到倒数第二位,有序部分:[5, 8]

第3轮遍历(未排序范围:0~2):

  • 比较 3 和 4:3<4,不交换 → [3, 4, 2, 5, 8]

  • 比较 4 和 2:4>2,交换 → [3, 2, 4, 5, 8]

  • 结果:第三大元素 4 冒泡到倒数第三位,有序部分:[4, 5, 8]

第4轮遍历(未排序范围:0~1):

  • 比较 3 和 2:3>2,交换 → [2, 3, 4, 5, 8]

  • 结果:第四大元素 3 冒泡到倒数第四位,有序部分:[3, 4, 5, 8]

此时数组已完全有序,无需进行第5轮遍历。最终排序结果:[2, 3, 4, 5, 8]

三、冒泡排序的C++代码实现

1. 基础版本(未优化)

根据上述原理,我们可以直接写出基础版本的冒泡排序代码。核心是双重循环:外层循环控制遍历轮数(最多n-1轮,n为数组长度),内层循环控制每轮的相邻元素比较与交换。

#include<iostream>#include<vector>usingnamespacestd;// 冒泡排序基础版本(升序)voidbubbleSortBasic(vector<int>&arr){intn=arr.size();// 外层循环:控制排序轮数,最多需要n-1轮for(inti=0;i<n-1;++i){// 内层循环:每轮比较相邻元素,排除已排序的末尾i个元素for(intj=0;j<n-1-i;++j){// 如果前一个元素大于后一个,交换if(arr[j]>arr[j+1]){swap(arr[j],arr[j+1]);// C++标准库swap函数,交换两个元素}}}}// 打印数组voidprintArray(constvector<int>&arr){for(intnum:arr){cout<<num<<" ";}cout<<endl;}intmain(){vector<int>arr={5,3,8,4,2};cout<<"排序前:";printArray(arr);bubbleSortBasic(arr);cout<<"排序后:";printArray(arr);return0;}

2. 优化版本(添加有序标记)

基础版本存在一个问题:如果数组在第k轮(k < n-1)就已经完全有序,后续的轮数仍然会继续执行,造成不必要的性能浪费。

优化思路:添加一个有序标记(flag)。每轮遍历开始前将flag设为true,若本轮发生了元素交换,则将flag设为false;如果某轮遍历结束后flag仍为true,说明数组已完全有序,直接退出循环即可。

#include<iostream>#include<vector>usingnamespacestd;// 冒泡排序优化版本(添加有序标记)voidbubbleSortOptimized(vector<int>&arr){intn=arr.size();boolisSorted;// 标记数组是否已有序for(inti=0;i<n-1;++i){isSorted=true;// 初始假设本轮遍历后数组有序for(intj=0;j<n-1-i;++j){if(arr[j]>arr[j+1]){swap(arr[j],arr[j+1]);isSorted=false;// 发生交换,说明数组尚未有序}}if(isSorted){break;// 若未发生交换,直接退出循环,无需后续遍历}}}// 打印数组voidprintArray(constvector<int>&arr){for(intnum:arr){cout<<num<<" ";}cout<<endl;}intmain(){vector<int>arr={5,3,8,4,2};cout<<"排序前:";printArray(arr);bubbleSortOptimized(arr);cout<<"排序后:";printArray(arr);return0;}

3. 代码运行结果

上述两个版本的代码运行后,输出结果均为:

排序前:5 3 8 4 2 排序后:2 3 4 5 8

四、冒泡排序的性能分析

1. 时间复杂度

  • 最坏情况:数组完全逆序。此时每轮都需要进行n-1-i次比较和交换,总比较次数为 (n-1) + (n-2) + … + 1 = n(n-1)/2,时间复杂度为 O(n²);

  • 最好情况:数组已完全有序(优化版本)。此时只需进行1轮遍历(n-1次比较,0次交换),时间复杂度为 O(n);

  • 平均情况:时间复杂度为 O(n²)。

2. 空间复杂度

冒泡排序是原地排序算法,排序过程中只需要额外的常数级空间(用于存储循环变量、有序标记等),空间复杂度为 O(1)。

3. 稳定性

冒泡排序是稳定排序算法。因为只有当相邻元素严格大于(或小于)时才会交换,相等元素不会发生交换,因此它们的相对位置不会改变。

五、冒泡排序的适用场景

由于冒泡排序的时间复杂度为 O(n²),效率较低,因此不适合处理大规模数据。其适用场景主要包括:

  • 排序算法入门学习(理解交换排序的核心思想);

  • 处理小规模数据(数据量n ≤ 1000,对效率要求不高);

  • 数组接近有序的场景(优化版本可快速退出,效率接近 O(n))。

六、总结

冒泡排序是最基础的排序算法之一,核心是“相邻比较、逐步冒泡”。虽然效率不高,但原理简单、代码实现容易,是入门排序算法的绝佳选择。本文介绍了冒泡排序的原理、过程演示、基础版与优化版C++代码,并分析了其性能和适用场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 19:25:05

挂马方式与检测技术深度解析

挂马方式与检测技术深度解析 在当今的Web安全攻防战场上&#xff0c;挂马早已不再是简单的“插入一段iframe”就能概括的行为。它已演变为一场融合了漏洞利用、社会工程、代码混淆甚至人工智能生成内容&#xff08;AIGC&#xff09;的综合性攻击手段。黑客通过植入恶意代码&…

作者头像 李华
网站建设 2026/4/25 19:25:04

逆向解密webshell源码全过程解析

逆向解密webshell源码全过程解析 在一次日常的群聊“闲逛”中&#xff0c;一个链接突然弹了出来——附言只有短短一句&#xff1a;“这 webshell 不一般&#xff0c;你看看&#xff1f;” 好奇心瞬间被点燃。不是因为它是后门&#xff0c;而是因为它“不一般”。 点开链接&a…

作者头像 李华
网站建设 2026/4/25 19:25:07

深度学习实验15代码 验证LSTM模型的长程依赖能力

import torch import torch.nn as nn import torch.optim as optim import numpy as np import matplotlib.pyplot as plt import random# 设置随机种子&#xff0c;确保整个实验可复现 def set_seed(seed42):torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)np.rando…

作者头像 李华
网站建设 2026/4/24 17:30:42

Forest项目中MySQL替换Derby数据库的完整配置

Forest项目中MySQL替换Derby数据库的完整配置 在开发企业级Java应用时&#xff0c;我们常常从轻量级数据库起步——比如Apache Derby&#xff0c;它嵌入式运行、无需额外部署&#xff0c;非常适合演示或本地测试。但一旦项目进入集成测试甚至预生产阶段&#xff0c;就会面临真实…

作者头像 李华
网站建设 2026/4/23 21:38:58

熔融缩聚动力学:聚酯反应速率常数测定

Z-Image-ComfyUI 图像生成系统的动态性能分析 在当前AIGC技术飞速发展的背景下&#xff0c;图像生成模型早已不再局限于“能否画出一张好看图片”的初级阶段。真正的挑战在于&#xff1a;如何让高质量生成变得足够快、足够稳、足够可控&#xff1f;这不仅是用户体验的问题&…

作者头像 李华