【基础算法】之 冒泡排序优化
冒泡排序思想
基本思想: 冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来(假设从小到大),即为较大的数慢慢往后排,较小的数慢慢往前排。
直观表达,每一趟遍历,将一个最大的数移到序列末尾。
下图演示排序流程:

下面是传统冒泡排序写法 时间复杂度O(n^2):
public static void bubbleSort(int[] nums) {int length = nums.length;for (int i = 0; i < length; i++) {System.out.println("i=" + i);for (int j = 0; j + 1 < length -i; j++) {System.out.println("内层循环次数:====================-" + j);if (nums[j] > nums[j + 1]) {int tem = nums[j];nums[j] = nums[j + 1];nums[j + 1] = tem;}}System.out.println("=======第" + i + " 轮外循环执行==============================");for (Integer integer : nums) {System.out.println(integer);}}}
执行下看看效果:



第一轮 5次 ,第二轮 4次,第三轮 3次, 第四轮 2次 ,第五轮 1次 ,第六轮0次
但是当我们遇到下面这种序列
即: 1,2,3,5,4 我们只需要排一趟就可以了 而无需后续的循环。
初次优化:
基于这种情况我们给出了下面这种优化。
通过增加一个标志位 flag ,若在某轮「内循环」中未执行任何交换操作,则说明数组已经完成排序,直接返回结果即可。
public static void bubbleSort1(int[] nums) {int length = nums.length;//定义标志位标记已经有序或无序boolean flag = false;for (int i = 0; i < length; i++) {System.out.println("i=" + i);flag = true;for (int j = 0; j + 1 < length - i; j++) {System.out.println("内层循环次数:====================-" + j);if (nums[j] > nums[j + 1]) {int tem = nums[j];nums[j] = nums[j + 1];nums[j + 1] = tem;//交换后对flag置false,表示已经处理成有序flag = false;}}// 已经排好序了 无需后续循环了if (flag) {break;}System.out.println("=======第" + i + " 轮外循环执行==============================");for (Integer integer : nums) {System.out.println(integer);}}}
在看下执行效果:


第一轮 5次 ,第二轮 4次,第三轮 3次 ,第四轮 2次
很明显外层减少了循环次数
优化后的冒泡排序的最差和平均时间复杂度仍为 O(N^2) ;在输入数组 已排序 时,达到 最佳时间复杂度 O(N) 。
继续优化:
然而这种优化只能做到某一次已经排好序的时候我们直接跳跳出来,基于第一种优化我们得到一种启发:当一个数组接近有序的时候我们往往只需要在某一个小范围内排序即可,我们可以用一个标记来表示这个范围的下限,例如遇到下面的情况

然而我们发现,每次排序前或排序后数组的后面都有一部分已经有序,这时我们只要记下最后一次排下的数组的下标,下次排序的时候就可以只排序到此下标位置即可

目的就是减少内层循环比较的次数
public static void bubbleSort2(int[] nums) {int length = nums.length;int index = length;//每一次我们找到无序区的上界int maxIndex = 0;//定义标志位标记已经有序或无序boolean flag = false;for (int i = 0; i < length; i++) {System.out.println("i=" + i);flag = true;for (int j = 0; j + 1 < index; j++) {System.out.println("内层循环次数:====================-" + j);if (nums[j] > nums[j + 1]) {int tem = nums[j];nums[j] = nums[j + 1];nums[j + 1] = tem;//交换后对flag置false,表示已经处理成有序flag = false;//注意不要在这里直接将index置为jmaxIndex = j + 1;}}// 已经排好序了 无需后续循环了if (flag) {break;}//若排序过则将index置为最后一次交换的坐标,若没有则表示已经有序index = maxIndex;System.out.println("=======第" + i + " 轮外循环执行==============================");for (Integer integer : nums) {System.out.println(integer);}}}
再次执行看看效果:


第一轮 5次 ,第二轮 3次,第三轮 2次 ,第四轮 1次
很明显内层循环也减少了很多
优化后的冒泡排序的最差和平均时间复杂度仍为 O(N^2) ;在输入数组 已排序 时,达到 最佳时间复杂度 O(1) 。
其实还可以再优化, 一层外循环 执行2个同级的内循环( 正着扫描得到最大值, 反着扫描得到最小值)

总结
主要从以下2方面优化了传统的冒泡排序写法
// 1、减少外层循环次数
// 2、减少内层循环次数
相关文章:

【基础算法】之 冒泡排序优化
冒泡排序思想基本思想: 冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来(假设从小到大),即为较大的数慢慢往后排,较小的数慢慢往前排。直观表达,每一趟遍历,…...
Python | 线程锁 | 3分钟掌握【同步锁】(Threading.Lock)
文章目录概念无锁加锁死锁解决死锁概念 threading.Lock 同步锁,可以用于保证多个线程对共享数据的独占访问。 当一个线程获取了锁之后,其他线程在此期间将不能再次获取该锁,直到该线程释放锁。这样就可以保证共享数据的独占访问,…...

Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)
Linux下安装MySQL8.0的详细步骤 第一步:下载安装配置 第二步:修改密码,并设置远程连接(为了可以在别的机器下面连接该mysql) 第三步:使用Navicat客户端连接 搞了一台云服务器,首先要干的活就是…...

leaflet 绘制多个点的envelope矩形(082)
第082个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何根据多边形的几个坐标点来绘制envelope矩形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共78行)安装插件相关API参考:专栏目标示例…...

CAJ论文怎么批量免费转换成Word
大家都知道CAJ文件吗?这是中国学术期刊数据库中的文件,这种文件类型比较特殊。如果想要提取其中的内容使用,该如何操作呢?大家可以试试下面这种免费的caj转word的方法,多个文档也可以一起批量转换。准备材料:CAJ文档、…...
面试必问: 结构体大小的计算方法
结构体大小的计算需同时满足以下几点 一、结构体成员的偏移量必须是当前成员大小的整数倍。(0是任何数的整数倍) 举一个例子 struct Test1{char a; // 当前偏移量为0,是char所占字节数1的整数倍 所以所占大小为1char b; …...
Java中super函数的用法
1 问题 Java中super函数有很多方法,在使用的时候我们应该如何正确区分? 2 方法 三种用法: 访问父类的方法。 调用父类构造方法。 访问父类中的隐藏成员变量。 class A{ int x,y; A(int x,int y){ System.out.println("A"); } } cla…...

第十一届“泰迪杯”数据挖掘挑战赛携“十万”大奖火热来袭
第十一届“泰迪杯”数据挖掘挑战赛 竞赛组织 主办单位: 泰迪杯数据挖掘挑战赛组织委员会 承办单位: 广东泰迪智能科技股份有限公司 人民邮电出版社 协办单位: 重庆市工业与应用数学学会、广东省工业与应用数学学会、广西数学学会、河北省工业…...

分享三个可以在家做的正规兼职工作,看到就是赚到
你可以在家做正式的兼职工作。在线兼职工作值得考虑,时间相对自由。在线兼职收入可能不如线下滴滴和外卖立竿见影,但仍然可以坚持收入。有些人比工作工资发展得更高。当然,天上不会有馅饼,不劳无获。那么有哪些正规的兼职可以在家…...

javaFx实现鼠标穿透画布,同时操作画布和桌面,背景透明,类似ppt批注
一、功能需要由来和大致效果 今天,我们要用javaFx来实现一个鼠标穿透画布的功能,该需求来自于在我们的javaFx桌面应用中,需要实现一个悬浮的桌面侧边工具栏,在工具栏中有画笔绘制,批注的功能,能够实现在任何…...

客户服务知识库的最佳实践7个步骤
每个公司的声誉都依赖于客户,如果客户因为想要购买你的产品找到你,但是了解到你的客户服务做的不好,可能也会放弃你的产品,就像市场营销依赖于潜在客户的关系一样,公司的服务部门也需要依赖于现有客户的关系࿰…...

多重继承的虚函数表
同一个类,不同对象使用同一张虚函数表 不同类使用不同的虚函数表 子类自己添加的虚函数(非重写),在VS中是将此放在第一个继承类的虚函数表里. #include <iostream> using namespace std;class Father { public:virtual void func1() { cout << "Father::f…...
第11篇:Java开发工具使用和代码规范配置
目录 1、IntelliJ IDEA 简介 2. IntelliJ IDEA 下载 3. IntelliJ IDEA 安装和使用 3.1 安装到Windows下 3.2 快速编写 Hello World 程序...
Rust模式匹配
模式匹配 模式匹配是从函数式编程语言(例如:Haskell,Lisp)吸收而来的,用于为复杂的类型系统提供一个轻松的解构能力。rust使用match来提供模式匹配的功能。mathc类似于其它编程语言中的switch-case,但是远…...
GIT:【基础一】必要配置和命令
目录 一、Git安装 二、基础命令 1.git config -l:git配置详细信息 2.git config --system -l:本地git系统自动配置的信息 3.git config --global -l:本地git用户自动配置的信息 4.where git: windows查看git安装目录 5.git各配置…...

黑马程序员-Linux系统编程-01
课程链接 01-Linux命令基础习惯-Linux系统编程_哔哩哔哩_bilibili 课程重点笔记 01-linux命令基础习惯 终端 终端:一切输入、输出的总称,因此终端并不是一定指的是命令行,只要是能进行输入或者输出即可,但是在linux终端上‘’内…...

Python|每日一练|动态规划|图算法|散列表|数组|双指针|单选记录:不同路径|求两个给定正整数的最大公约数和最小公倍数|删除有序数组中的重复项
1、不同路径(数学,动态规划) 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”…...

Java常用框架(一)
思维导图 常见知识点 一、SpringBoot 1.简单介绍一下Spring及其优缺点 1.1 概念 重量级企业开发框架EJB的替代品,通过依赖注入、面向切面编程,使用简单Java对象POJO为企业Java开发提供了相对简单的方法。 1.2 优缺点 1.2.1 优点 组件代码轻量级 …...

基于 DSP+FPGA 的高清图像跟踪系统研制
目标识别与跟踪技术是目前图像处理研究的重点方向,在军事和民用领域中 具有广泛的应用价值,如精确制导武器、导弹飞机预警等军事领域,如交通管理、 刑事侦查等民用领域。其中,如何在复杂的背景中,提取、识别与跟踪特定…...
apisix部署
使用k8s部署前打包镜像: FROM centos:7 ARG APISIX_VERSION2.11.0 LABEL apisix_version“${APISIX_VERSION}” RUN yum install -y https://repos.apiseven.com/packages/centos/apache-apisix-repo-1.0-1.noarch.rpm && yum install -y https://repos…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...