排序---冒泡排序(Bubble Sort)

一、算法核心概念

冒泡排序是一种简单的交换排序算法,其核心思想是:通过重复遍历待排序数组,每次比较相邻的两个元素,若它们的顺序错误(如升序排序中前一个元素大于后一个),则交换它们的位置。经过多轮遍历后,较大的元素会像“气泡”一样逐渐“上浮”到数组的末尾,最终使整个数组有序。

二、基本工作原理

升序排序为例,冒泡排序的工作流程可概括为:

  1. 初始状态:整个数组为“未排序区间”(需排序的元素范围);
  2. 每轮遍历:从数组头部开始,依次比较相邻元素(arr[j]arr[j+1]),若arr[j] > arr[j+1],则交换两者位置;
  3. 范围收缩:每轮遍历结束后,当前未排序区间中最大的元素会“浮”到区间的末尾,因此下一轮的未排序区间可缩小1个元素(无需再检查已“浮”到末尾的元素);
  4. 终止条件:当某轮遍历中没有发生任何元素交换时,说明数组已完全有序,排序结束。
三、步骤演示(实例解析)

以数组[5, 3, 8, 4, 2]为例,演示升序冒泡排序的过程:

轮次未排序区间遍历中的比较与交换本轮结束后数组是否发生交换
1[0,4](全数组)比较5&3→交换→[3,5,8,4,2];
比较5&8→不交换;
比较8&4→交换→[3,5,4,8,2];
比较8&2→交换→[3,5,4,2,8]
[3,5,4,2,8]
2[0,3](前4个元素)比较3&5→不交换;
比较5&4→交换→[3,4,5,2,8];
比较5&2→交换→[3,4,2,5,8]
[3,4,2,5,8]
3[0,2](前3个元素)比较3&4→不交换;
比较4&2→交换→[3,2,4,5,8]
[3,2,4,5,8]
4[0,1](前2个元素)比较3&2→交换→[2,3,4,5,8][2,3,4,5,8]
5[0,0](仅第1个元素)无相邻元素可比较[2,3,4,5,8]否(排序结束)
四、时间复杂度与空间复杂度
  • 时间复杂度

    • 最坏情况:数组完全逆序,需执行n-1轮遍历,每轮比较n-i次(i为轮次),总操作次数为n+(n-1)+...+1 = n(n-1)/2,故为O(n²)
    • 最好情况:数组已完全有序,若添加“交换标志”优化,仅需1轮遍历(n-1次比较)即可判断有序,故为O(n)
    • 平均情况:O(n²)(适用于随机无序数组)。
  • 空间复杂度
    仅需常数个临时变量(用于交换元素和记录标志),故为O(1)(原地排序)。

五、稳定性分析

冒泡排序是稳定的排序算法

  • 稳定性定义:若数组中存在相等元素,排序后它们的相对顺序与原数组一致,则算法稳定。
  • 原因:冒泡排序仅在相邻元素严格逆序(如arr[j] > arr[j+1])时才交换,若arr[j] == arr[j+1],不会触发交换,因此相等元素的相对顺序保持不变。
六、优化策略

基础版冒泡排序在数组已部分有序时仍会执行不必要的遍历,可通过以下优化提升效率:

1. 交换标志优化(核心优化)

添加一个布尔变量(如swapped),记录每轮是否发生交换。若某轮未发生交换,说明数组已有序,可直接终止排序。

2. 记录最后交换位置(进阶优化)

每轮遍历中,记录最后一次发生交换的位置lastSwapIndex。下一轮遍历的终点可设为lastSwapIndex(因为该位置之后的元素已有序),减少无效比较。

七、C++实现代码
1. 基础版实现
#include <iostream>
#include <vector>
using namespace std;// 基础版冒泡排序(升序)
void bubbleSortBasic(vector<int>& arr) {int n = arr.size();// 外层循环:控制轮次(最多n-1轮)for (int i = 0; i < n - 1; ++i) {// 内层循环:遍历未排序区间[0, n-1-i]for (int j = 0; j < n - 1 - i; ++j) {if (arr[j] > arr[j + 1]) {swap(arr[j], arr[j + 1]); // 交换逆序元素}}}
}int main() {vector<int> arr = {5, 3, 8, 4, 2};bubbleSortBasic(arr);for (int num : arr) {cout << num << " "; // 输出:2 3 4 5 8}return 0;
}
2. 优化版实现(交换标志+最后交换位置)
#include <iostream>
#include <vector>
using namespace std;// 优化版冒泡排序(升序)
void bubbleSortOptimized(vector<int>& arr) {int n = arr.size();int lastSwapIndex = 0; // 记录最后一次交换的位置int border = n - 1;    // 当前未排序区间的右边界(初始为数组末尾)for (int i = 0; i < n - 1; ++i) {bool swapped = false; // 标志位:本轮是否发生交换// 内层循环仅遍历到border(减少无效比较)for (int j = 0; j < border; ++j) {if (arr[j] > arr[j + 1]) {swap(arr[j], arr[j + 1]);swapped = true;lastSwapIndex = j; // 更新最后交换位置}}border = lastSwapIndex; // 收缩未排序区间右边界if (!swapped) break;    // 未交换,数组已有序,提前终止}
}int main() {vector<int> arr = {5, 3, 8, 4, 2};bubbleSortOptimized(arr);for (int num : arr) {cout << num << " "; // 输出:2 3 4 5 8}return 0;
}
八、适用场景与局限性
适用场景:
  1. 小规模数据排序:数据量较小时(如n < 100),冒泡排序实现简单,性能可接受;
  2. 几乎有序的数据:若数组已接近有序(仅少数元素逆序),优化后的冒泡排序可快速完成排序(接近O(n)复杂度);
  3. 教学场景:算法逻辑直观,易于理解,适合作为入门排序算法讲解。
局限性:
  1. 大规模数据效率低:时间复杂度为O(n²),对于n > 1000的数组,排序速度远低于O(nlogn)级算法(如快速排序、归并排序);
  2. 交换操作频繁:每轮可能发生多次相邻元素交换,实际运行时间比同复杂度的选择排序更长(选择排序每轮仅1次交换)。

冒泡排序是一种直观、简单的排序算法,核心通过“相邻元素比较交换”使大元素逐步上浮。尽管其时间复杂度较高(O(n²)),但在小规模或近乎有序的数据场景中仍有应用价值。通过“交换标志”和“收缩边界”优化,可显著提升其在部分有序数据上的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96028.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96028.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MCP(模型上下文协议)入门教程

MCP&#xff08;模型上下文协议&#xff09;入门教程&#xff1a;连接AI与外部世界的万能插座 1 MCP是什么&#xff1f; 1.1 基本概念 MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;是一个开放协议&#xff0c;专门用于AI模型与外部数据源和…

GO开发遇到的报错问题合集

本文将记录平时在go开发中遇到的一些错误信息&#xff0c;踩过的坑&#xff0c;并分析原因及提供解决方法&#xff0c;持续更新中...1、grpc 接口请求报错&#xff1a;Error: 13 INTERNAL: Response message parsing error: invalid wire type 7 at offset 316原因&#xff1a;…

Node.js 做 Web 后端优势为什么这么大?

Node.js自诞生以来&#xff0c;一步步演变变为现代Web后端开发的基石之一。无论是初创公司快速构建原型&#xff0c;还是大型企业支撑高并发业务&#xff0c;好像它哪儿哪儿都在&#xff0c;甚至还有人觉得它威胁到了PHP的地位。 那为什么Node.js 做 Web 后端优势那么大&#x…

JAVA:IO流之字节输入流InputStream基础

我们知道&#xff0c;文件是写在磁盘中的&#xff0c;而程序的运行又要借助于内存。那么怎么实现内存和磁盘的“互动”呢&#xff1f;这就要借助“流”来实现了。内存具体指的就是我们的java程序&#xff0c;而磁盘具体指的是我们的文件。从磁盘到内存叫输入&#xff0c;从内存…

23种设计模式——桥接模式 (Bridge Pattern)详解

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a;设计模式 ✨特色专栏&#xff1a;知识分享 &#x…

Python爬虫实战:研究Axes Grid模块,构建旅游平台酒店数据采集和分析系统

1. 引言 1.1 研究背景 随着互联网技术的飞速发展,全球数据总量呈现指数级增长。据国际数据公司(IDC)预测,到 2025 年全球数据圈将达到 175ZB,其中非结构化数据占比超过 80%。这些数据广泛分布于各类网站平台,包含着用户行为、市场趋势、产品特征等丰富信息。如何高效获…

光照边疆平台|面向边疆地区的现代化内容与信息服务系统

光照边疆平台&#xff5c;面向边疆地区的现代化内容与信息服务系统聚焦“边疆资讯 边疆风光 用户互动 后台可视化管控”的高颜值内容平台&#xff0c;适合展示、传播与运营边疆主题内容。系统定位与价值 主题聚焦&#xff1a;以“边疆”为核心&#xff0c;统一内容语义与视觉…

删除元素(不是删除而是覆盖)快慢指针 慢指针是覆盖位置,快指针找元素

&#x1f4dd; 题目&#xff1a;移除元素题目描述&#xff1a; 给定数组和值val&#xff0c;原地移除所有等于val的元素&#xff0c;返回新长度。例子&#xff1a; nums [3,2,2,3], val 3 → nums [2,2,_,_], return 2&#x1f525; 暴力法思路&#xff1a;暴力法想法&#…

10 【C++】泛型编程

文章目录前言泛型编程&#xff08;模板&#xff09;1. 函数模板1.1 函数模板格式1.2 函数模板的实例化隐式实例化显式指定模板参数实例化1.3 函数模板实例化的原理1.4 模板参数的匹配原则2. 类模板2.1 类模板的格式2.2 类模板的实例化2.3 类模板实例化的原理2.4 类模板的匹配原…

【基于YOLO和Web的交通工具识别系统】

系统功能 视频检测&#xff1a;对输入的视频流进行实时或离线分析&#xff0c;自动识别视频中出现的交通工具&#xff08;如飞机、自行车等&#xff09;及行人&#xff0c;输出包含目标类别、位置等信息的检测结果。摄像检测&#xff1a;通过连接摄像头设备&#xff0c;对实时…

Python进程,线程

目录 一、多任务 1.1定义 1.2具体体现 1.3并发和并行 1.3.1并发操作 1.3.2并行操作 1.3.3对比 二、进程 2.1概念 2.2特点 2.3进程状态 2.4多进程 2.5多进程实现 2.6进程锁 三、线程 3.1概念 3.2特点 3.3适用场景 3.4多线程实现 四、对比 4.1关系对⽐ 4.2区…

【Element Plus 表单组件样式统一 CSS 文字特效实现指南】

Element Plus 表单组件样式统一 & CSS 文字特效实现指南 前言 在使用 Element Plus 组件库开发表单页面时&#xff0c;我们遇到了一个看似简单却很有趣的问题&#xff1a;el-input、el-select 和 el-textarea 在禁用状态下的文字颜色不一致。通过深入研究&#xff0c;我们…

网络通信与协议栈 -- OSI,TCP/IP模型,协议族,UDP编程

网络通信的核心是实现不同主机上进程间的数据交换&#xff0c;其技术体系围绕 “协议分层模型” 展开&#xff0c;向下依赖硬件介质传输电 / 光信号&#xff0c;向上支撑各类网络应用&#xff08;如网页浏览、文件传输&#xff09;。本文结合 OSI 理论框架与 TCP/IP 工业标准&a…

HarmonyOS 新一代声明式 UI 弹窗机制:从 AlertDialog 到 CustomDialogController 的深度解析与实践

好的&#xff0c;请看这篇关于 HarmonyOS 新一代声明式 UI 弹窗机制的技术文章。 HarmonyOS 新一代声明式 UI 弹窗机制&#xff1a;从 AlertDialog 到 CustomDialogController 的深度解析与实践 引言 在 HarmonyOS 应用开发中&#xff0c;弹窗&#xff08;Dialog&#xff09;是…

混合推理模型(快思考、慢思考模型)

目录基础transformer架构、transformers库预训练模型的微调&#xff08;Fine-tuning&#xff09;预训练微调的大模型应用模式base 模型、instruct 模型区别Hugging Face 上如何查看base模型、instruct模型混合推理模型大模型里的快思考 vs 慢思考qwen3模型含特殊 ChatML / 模型…

prometheus+grafana搭建

部署 prometheus 安装 # 1,下载 wget https://github.com/prometheus/prometheus/releases/download/v2.45.1/prometheus-3.5.0.linux-amd64.tar.gz# 2,部署 tar -zxvf prometheus-3.5.0.linux-amd64.tar.gz -C /opt/ cd /opt/ mv ./prometheus-3.5.0.linux-amd64 …

MR30分布式I/O在面机装备中的应用

随着食品加工行业向自动化、智能化转型&#xff0c;面机装备对控制系统的响应速度、布线灵活性及稳定性提出了更高要求。本案例以某大型食品机械制造企业的全自动面条生产线升级项目为背景&#xff0c;引入 MR30 分布式 IO 模块替代传统集中式 IO 方案。通过将 MR30 分布式 IO …

Matlab使用小技巧合集(系列四):Table类型高效用法与数据处理实战

Matlab使用小技巧合集(系列四):Table类型高效用法与数据处理实战 在科研数据处理和论文写作过程中,结构化数据的管理极为重要。Matlab的table类型为研究生和科研人员提供了灵活、高效的数据存储与处理方式,尤其适合实验结果整理、分组统计、数据预处理等场景。本文将系统介…

STM32的时钟系统与时钟树的配置

STM32的时钟系统是其微控制器&#xff08;MCU&#xff09;的核心组成部分&#xff0c;负责为CPU、外设和存储器等模块提供精确的时序信号。其设计灵活且复杂&#xff0c;通过多级时钟树&#xff08;Clock Tree&#xff09;实现时钟源的选择、分频和分配。以下是详细介绍&#x…

NV 工具metrics分析(ncu, nsys/torch profiler)

以下分析都以A100硬件架构为例; Theoretical Max Active Warps per SM: 64 Register number: 512 (规定每个thread不能超过256) Theoretical Active Warps per SM [warp]&#xff1a;512//registers_per_thread*4, which defines theoretical active warp occupancy Waves P…