算法基础一:冒泡排序
一、冒泡排序
1、定义
冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
冒泡排序是所有排序算法中最简单、最易实现的算法,有时也称为起泡排序算法。
使用冒泡排序算法对 n 个数据进行排序,实现思路是:从待排序序列中找出一个最大值或最小值,这样的操作执行 n-1 次,最终就可以得到一个有序序列。
2、过程分析
举个例子,对 {14, 33, 27, 35, 10} 序列进行升序排序(由小到大排序),冒泡排序算法的实现过程是:
- 从 {14, 33, 27, 35, 10} 中找到最大值 35;
- 从 {14,33,27,10} 中找到最大值 33;
- 从 {14, 27, 10} 中找到最大值 27;
- 从 {14, 10} 中找到最大值 14。
由此,我们就得到了一个有序序列 {10, 14, 27, 33, 35}。
那么,如何从待排序序列中找到最大(或最小)的值呢?以找最大值为例,遍历待排序序列,过程中不断地比较相邻两个元素的值,如果后者比前者的值小就交换它们的位置。遍历完成后,最后一个元素就是当前待排序序列中最大的。
例如,从 {14, 33, 27, 35, 10} 中找到最大值 35 的过程如下:
1) 比较 14 和 33 的大小,显然后者更大,不需要交换它们的位置,序列不发生改变。
2) 比较 33 和 27 的大小,前者大于后者,交换它们的位置,新的序列如下图所示。
3) 比较 33 和 35 的大小,后者更大,不需要交换它们的位置,序列不发生改变。
4) 比较 35 和 10 的大小,前者大于后者,交换它们的位置,新的序列如下图所示。
可以看到,序列中值最大的元素 35 被移动到了序列的末尾。整个查找最大值的过程中,最大的元素就像水里的气泡一样,一点一点地“冒”了出来,这也是将该算法命名为冒泡排序算法的原因。
采用同样的方法,我们可以很轻松地从 {14, 27, 33, 10} 中找到最大值 33。找到 33 后的新序列为:
从 {14, 27, 10} 中找到最大值 27 后,新的序列如下图所示:
从 {14, 10} 中找到最大值 14 后,新的序列如下图所示:
所有比 10 大的数都被一一找到,所以 10 必然是最小的数,这也是为什么“对 n 个数据进行排序,找最大值的过程只重复 n-1 次”的原因。
3、代码实现
如下是用冒泡排序算法对 { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70} 完成升序排序的C语言程序:
#include <stdio.h>
//函数声明
void Bubble_sort(int arr[], int len);int main(void)
{int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };//定义一个数组int len = sizeof(arr)/ sizeof(arr[0]);//计算数组长度 = 数组总字节数/每个元素的字节数Bubble_sort(arr, len);for (int i = 0; i < len; i++){printf("%d ", arr[i]);}return 0;
}void Bubble_sort(int arr[], int len)
{for (int i = 0; i < len - 1; i++)//循环次数(n - 1){for (int j = 0; j < len - i - 1; j++){//每次循环的两两比较元素if (arr[j] > arr[j + 1])//如果前一个数大于后一个,就把大的给往后放{int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}
如下是用冒泡排序算法对 {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70} 完成升序排序的 Python 程序:
#待排序序列
list = [22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70]
def Bubble_sort():#序列中有 n 个元素,就遍历 n-1 遍for i in range(len(list-1)):#从第 1 个元素开始遍历,比那里至 len(list)-1-ifor j in range(len(list)-1-i):#比较两个相邻元素的大小if list[j] > list[j+1]:#交换 2 个元素的位置list[j],list[j+1] = list[j+1],list[j]
Bubble_sort()
for i in list:print(i,end=" ")
二、双向冒泡排序
1、通过冒泡排序进阶:
先回忆一下普通的冒泡排序算法,比如对 {14, 33, 27, 35, 10} 进行升序排序,过程如下图所示:
图 1 普通的冒泡排序
从待排序序列的第一个元素开始,比较相邻元素的大小,找到最大(或最小)的元素并移动到序列的末尾。重复整个过程,最终就可以得到一个有序的序列。
双向冒泡排序算法对图 1 的排序过程进行了优化,接下来仍以 {14, 33, 27, 35, 10} 进行升序排序为例,带大家了解双向冒泡排序。
1) 最初的待排序序列是 {14, 33, 27, 35, 10},和普通的冒泡排序一样,从第一个元素 14 向后查找,通过相邻元素的比较,找到最大的元素并移动到序列的末尾,过程如下图所示:
图 2 第一轮从前向后冒泡
在图 2 的基础上,待排序序列变成了 {14, 27, 33, 10}。接下来从末尾元素 10 开始向前查找,通过相邻元素的比较,找到最小的元素并移动到序列的开头。
图 3 第一轮从后往前冒泡
经过了第 1 步,从元素 14 向后查找,找到了最大值 35;再从元素 10 向前查找,找到了最小值 10。最终,待排序序列变成了 {14, 27, 33}。
2) 采用和第 1 步相同的方法,从 {14, 27, 33} 中的第一个元素 14 开始向后查找,通过相邻元素的对比,最终可以找到最大值 33 并移动到序列的末尾,待排序序列变成了 {14, 27}。
图 4 第二轮从前往后冒泡
继续从 {14, 27} 中最后一个元素 27 开始向前查找,可以找到最小值 14 并移动到序列的开头,待排序序列变成了 {27}。
图 5 第二轮从后往前冒泡
3) 由于待排序序列 {27} 只有 1 个元素,不再需要冒泡排序,此时整个序列 {10, 14, 27, 33, 35} 就是一个升序序列。
2、代码实现
下面是使用双向冒泡排序对 { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 } 完成升序排序的C语言程序:
#include <stdio.h>// 函数声明
void bubble_sort(int arr[], int len);int main() {int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };int len = sizeof(arr) / sizeof(arr[0]); // 计算数组长度//insertion_sort(arr, len); // 调用插入排序函数bubble_sort(arr, len); // 调用插入排序函数// 打印排序后的数组for (int i = 0; i < len; i++) {printf("%d ", arr[i]);}return 0;
}void bubble_sort(int arr[], int len)
{int i, temp;int low = 0, high = len -1;while (low < high){for (i = low; i < high;i++){if (arr[i] > arr[i + 1]){temp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = temp;}}high--;for (i = high; i > low; i--){if (arr[i] < arr[i - 1]){temp = arr[i];arr[i] = arr[i - 1];arr[i - 1] = temp;}}low++;}}
下面是使用双向冒泡排序对{ 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 } 完成升序排序的 Python 程序:
list = [22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70] # 定义并初始化一个列表list
def Bubble_sort():temp,i = 0,0low, high = 0,len(list) -1while low<high:for i in range (low,high):if list[i] > list[i+1]:list[i],list[i+1] = list[i+1],list[i]high-=1for i in range (high,low,-1):if list[i] < list[i-1]:list[i], list[i-1] =list[i-1],list[i]low+=1Bubble_sort()
for i in list:print(i,end = " ")
相关文章:

算法基础一:冒泡排序
一、冒泡排序 1、定义 冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。 …...

云开发实战教程:手把手教你高效开发应用
声明:本文仅供实践教学使用,没有任何打广告成分 目录 1.引言 2.云开发 Copilot介绍 云开发 Copilot 的功能与特点 3.环境准备 步骤一登录账号 步骤二新建环境 4.开发实践 4.1AI 生成低代码应用 4.2AI 生成低代码页面/区块 4.3AI 优化低代码组件…...

Git基本操作快速入门(30min)
Git基本操作快速入门(30min) 文章目录 Git基本操作快速入门(30min)1. 建立本地仓库2. 本地仓库链接到远端仓库3. 将本地仓库推送到远端4. Git常用命令 作为一名程序员,使用Github来进行代码的版本管理是必修课…...

VS Code AI开发之Copilot配置和使用详解
随着AI开发工具的迅速发展,GitHub Copilot在Cursor、Winsuf、V0等一众工具的冲击下,推出了免费版本。接下来,我将为大家介绍GitHub Copilot的配置和使用方法。GitHub Copilot基于OpenAI Codex模型,旨在为软件开发者提供智能化的代…...
QT中使用OpenGL function
1.前言 QT做界面编程很方便,QTOpenGL的使用也很方便,因为QT对原生的OpenGL API进行了面向对象化的封装。 如: 函数:initializeOpenGLFunctions()...... 类:QOpenGLVertexArrayObject、QOpenGLBuffer、QOpenGLShader…...

STM32-笔记16-定时器中断点灯
一、实验目的 使用定时器 2 进行中断点灯,500ms LED 灯翻转一次。 二,定时器溢出时间计算 Tout:定时器溢出时间 Ft:定时器的时钟源频率 ARR:自动重装载寄存器的值(可设置ARR从0开始,但是计数到…...
Live555、FFmpeg、GStreamer介绍
Live555、FFmpeg 和 GStreamer 都是处理流媒体和视频数据的强大开源框架和工具,它们广泛应用于实时视频流的推送、接收、处理和播放。每个框架有不同的设计理念、功能特性以及适用场景。下面将详细分析这三个框架的作用、解决的问题、适用场景、优缺点,并…...
oracle基础:理解 Oracle SQL 中的 WHERE 后的 (+) 用法
在使用 Oracle 数据库进行 SQL 查询时,可能会遇到 WHERE 子句后带有 () 的语法。这是 Oracle 专有的外连接(Outer Join)表示法。虽然现代 SQL 标准推荐使用 LEFT JOIN 和 RIGHT JOIN 语法,但在某些遗留系统中,这种写法…...

【linux】进程间通信(IPC)——匿名管道,命名管道与System V内核方案的共享内存,以及消息队列和信号量的原理概述
目录 ✈必备知识 进程间通信概述 🔥概述 🔥必要性 🔥原理 管道概述 🔥管道的本质 🔥管道的相关特性 🔥管道的同步与互斥机制 匿名管道 🔥系统调用接口介绍 🔥内核原理 …...

【深度学习】卷积网络代码实战ResNet
ResNet (Residual Network) 是由微软研究院的何凯明等人在2015年提出的一种深度卷积神经网络结构。ResNet的设计目标是解决深层网络训练中的梯度消失和梯度爆炸问题,进一步提高网络的表现。下面是一个ResNet模型实现,使用PyTorch框架来展示如何实现基本的…...
org.apache.zookeeper.server.quorum.QuorumPeerMain
QuorumPeerMain源代码 package org.apache.zookeeper.server.quorum;import java.io.IOException; import javax.management.JMException; import javax.security.sasl.SaslException; import org.apache.yetus.audience.InterfaceAudience; import org.apache.zookeeper.audi…...

oscp学习之路,Kioptix Level2靶场通关教程
oscp学习之路,Kioptix Level2靶场通关教程 靶场下载:Kioptrix Level 2.zip 链接: https://pan.baidu.com/s/1gxVRhrzLW1oI_MhcfWPn0w?pwd1111 提取码: 1111 搭建好靶场之后输入ip a看一下攻击机的IP。 确定好本机IP后,使用nmap扫描网段&…...
SkyWalking java-agent 是如何工作的,自己实现一个监控sql执行耗时的agent
Apache SkyWalking 是一个开源的应用性能监控 (APM) 工具,支持分布式系统的追踪、监控和诊断。SkyWalking Agent 是其中的一个重要组件,用于在服务端应用中收集性能数据和追踪信息,并将其发送到 SkyWalking 后端服务器进行处理和展示。 SkyW…...

每天40分玩转Django:Django表单集
Django表单集 一、知识要点概览表 类别知识点掌握程度要求基础概念FormSet、ModelFormSet深入理解内联表单集InlineFormSet、BaseInlineFormSet熟练应用表单集验证clean方法、验证规则熟练应用自定义配置extra、max_num、can_delete理解应用动态管理JavaScript动态添加/删除表…...

查看vue的所有版本号和已安装的版本
1.使用npm查看Vue的所有版本: npm view vue versions2.查看项目中已安装的 Vue.js 版本 npm list vue...
钉钉h5微应用,鉴权提示dd.config错误说明,提示“jsapi ticket读取失败
这个提示大多是因为钉钉服务器没有成功读取到该企业的jsticket数据 1. 可能是你的企业corpid不对 登录钉钉管理后台 就可以找到对应企业的corpid 请严格使用这个corpid 。调用获取jsapi_ticket接口,使用的access_token对应的corpid和dd.config中传递的corpid不一致…...

【openGauss】正则表达式次数符号“{}“在ORACLE和openGauss中的差异
一、前言 正则作为一种常用的字符串处理方式,在各种开发语言,甚至数据库中,都有自带的正则函数。但是正则函数有很多标准,不同标准对正则表达式的解析方式不一样,本次在迁移一个ORACLE数据库到openGauss时发现了一个关…...
宏任务和微任务的区别
在 JavaScript 的异步编程模型中,宏任务(Macro Task)和微任务(Micro Task)是事件循环(Event Loop)机制中的两个重要概念。它们用于管理异步操作的执行顺序。 1. 宏任务 (Macro Task) 宏任务是较…...

数据库系统原理复习汇总
数据库系统原理复习汇总 一、数据库系统原理重点内容提纲 题型:主观题 1、简答题 第一章:数据库的基本概念:数据库、数据库管理系统、三级模式;两级映像、外码 第二章:什么是自然连接、等值连接; 第三…...

Linux day1204
五.安装lrzsz lrzsz 是用于在 Linux 系统中文件上传下载的软件。大家可能会存在疑问,我们用 MobaXterm 图形化界面就可以很方便的完成上传下载,为什么还要使用这个软件来 完成上传下载呢?实际上是这样的, Linux 的远程连接工具…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...