【排序算法】之冒泡排序

一、算法介绍

冒泡排序(Bubble Sort)是一种基础的排序算法,它的主要思想是通过重复遍历待排序的列表,比较每对相邻的元素并根据需要交换它们,使得每一遍遍历都能将未排序的最大(或最小)元素“冒泡”到正确的位置。以下是冒泡排序的详细步骤和特点:
1. 基本步骤:

  • 对于给定的未排序数组,从第一个元素开始,比较相邻的元素。
  • 如果前一个元素大于后一个元素,则交换它们的位置。
  • 对每一对相邻元素做同样的比较,从开始第一对到结尾的最后一对。这步做完后,最后的元素将会是最大的数。
  • 重复步骤1和2,但不包括最后一对,因为上一轮中它们已经排好序了。
  • 重复以上步骤,直到没有需要交换的元素,即数组完全排序。

2. 算法流程:

  • 一次完整的遍历称为一轮。
  • 每轮遍历中,最大的元素会“冒”到数组的末尾。
    继续进行下一轮遍历,直到所有元素都在正确的位置上。

3. 示例:

  • 对于数组 [5, 3, 8, 1, 2],第一轮遍历后,最大的数字8会移动到最后,数组变为 [5, 3, 1, 2, 8]。
    接下来的每一轮都会将剩余元素中的最大值移动到已排序部分的末尾,直到数组完全排序为 [1, 2, 3, 5, 8]。

4. 时间复杂度:

  • 平均和最坏情况下的时间复杂度都是 O( n 2 n^{2} n2),其中 n 是数组的长度。这是因为每个元素都要与其他所有元素比较一次。
  • 在最好情况下,如果数组已经排序,只需要进行 n-1 次比较即可完成排序,时间复杂度为 O(n)。

5. 空间复杂度:

  • 冒泡排序是原地排序算法,它不需要额外的存储空间,因此空间复杂度为 O(1)。

6. 稳定性:

  • 冒泡排序是稳定的排序算法,即相等的元素在排序后保持原有的相对顺序。

由于其效率较低,冒泡排序在实际应用中并不常见,但在我们自己学习和理解排序算法原理时很有用。在处理大量数据时,其他更高效的方法如快速排序、归并排序和堆排序更受欢迎。我们先通过简单的java代码来实现这种算法。

二、代码示例

以下代码是冒泡排序从小到大排序的示例

package com.datastructures;

import java.util.Arrays;

/**
 * 冒泡排序算法实现
 * @author hulei
 * @date 2024/5/7 11:41
 */


public class BubbleSort {
    public static void main(String[] args) {
        Integer[] array = {7,3,5,4,8,1,11,15,2};
        System.out.println("冒泡排序前数组:"+Arrays.toString(array));
        bubbleSort(array);
        System.out.println("冒泡排序后数组:"+Arrays.toString(array));
    }


    /**
     * 实现冒泡排序算法,对一个可比较元素数组进行排序。
     *
     * @param array 一个类型为E的数组,其中E必须实现Comparable接口,以便于元素之间的比较。
     *              该数组是待排序的数组。
     * @see java.lang.Comparable
     */
    public static <E extends Comparable<? super E>> void bubbleSort(E[] array){
        int length = array.length;
        // 外层循环控制排序的轮数,每轮确保最重(或最轻)的元素位置正确
        for (int i = 0; i < length -1; i++) {
            // 内层循环控制每轮排序中元素的比较,每次比较相邻的两个元素
            for (int j = 0; j < length -1-i; j++) {
                // 如果当前元素大于下一个元素,则交换它们的位置,使得较大的元素逐渐向数组尾部移动
                if(array[j].compareTo(array[j+1])>0){
                    swap(array,j+1,j);
                }
            }
            
        }

    }

    /**
     * 交换数组中两个元素的位置。
     * @param array 要进行交换的数组。
     * @param index1 要交换的第一个元素的索引。
     * @param index2 要交换的第二个元素的索引。
     * @param <E> 数组元素的类型。
     */
    private static <E> void swap(E[] array, int index1, int index2) {
        // 临时变量用于存储第一个元素,以便后续交换
        E temp = array[index1];
        array[index1] = array[index2]; // 将第二个元素的值赋给第一个元素
        array[index2] = temp; // 将之前存储的第一个元素的值赋给第二个元素
    }
}


在这里插入图片描述
代码逻辑比较简单,使用了两层for循环,外层控制循环的论数,n个元素就需要循环排序n轮。
第一轮外循环:
内层循环是相邻元素比较:

  • 第一层内循环从第一个元素A开始比较,相邻比较,如果大于第二个元素,就把第一个元素和第二个元素交换位置。

  • 第二层内循环再把这个A元素(这个元素索引位置已经移动到了第二的位置)和第三个元素比较,如果大于第三个,就把第二个元素A和第三个元素交换位置,交换后元素A移动到了第三的位置。

  • 第三层内循环再把这个元素A(这个元素索引位置已经移动到了第三的位置)和第四个元素比较,如果A小于第四个元素B,则AB不交换,元素A遇到第一个比自己大的元素B

  • 第四层内循环把元素B和第五个元素C比较,如果B小于C,则B遇到第一个比自己大的元素CBC不交换。

  • 第五层内循环把元素C和第六个元素D比较,如果C大于D,则把第五个元素C和第六个元素D交换。

  • 第六层内循环从元素C(元素C在第六的位置)开始和第七个元素E比较



    以此类推直到第一轮内存循环全部结束,最大的元素K被排在最后一位

接着开始第二轮外层循环,内部还是从第一个元素开始与相邻元素比较,比较过并交换的过程同上类似,但是内层循环最终的边界是右边倒数第二个元素,此轮结束后会把第二大的元素M排在右边倒数第二位,即K的前一位




一直到外层循环都结束,通过n轮循环把n个元素按照从小到大的顺序排好了。

三、代码优化

注意以上代码代码其实不是最优代码,因为无论数组是否排序,内存和外层都要进行全部的循环才能完成排序,时间复杂度总是为O( n 2 n^{2} n2),但有一种情况,比如数组已经从小到大排序好了,再进行那么多次循环岂不是浪费?
如果数组已经从小到大排序好了,在第一轮外层循环时就已经能判断出来,判断时会发现下一个元素总是大于前一个,即没有发生过元素交换。
这里提供一个交换标识来判断跳出循环,保证在已排序的情况下不做无谓的循环,优化后代码如下:
bubbleSort方法里加了一个交换标识swapped,第一轮内部循环结束后,swapped为false则说明已排序好,跳出外层循环,其实只进行了第一轮内部循环的n-1次遍历,时间复杂度为O(n-1)

    public static <E extends Comparable<? super E>> void bubbleSort(E[] array){
        int length = array.length;
        boolean swapped; // 标记在某一轮内是否进行了交换
        // 外层循环控制排序的轮数,每轮确保最重(或最轻)的元素位置正确
        for (int i = 0; i < length -1; i++) {
            swapped = false;
            // 内层循环控制每轮排序中元素的比较,每次比较相邻的两个元素
            for (int j = 0; j < length -1-i; j++) {
                // 如果当前元素大于下一个元素,则交换它们的位置,使得较大的元素逐渐向数组尾部移动
                if(array[j].compareTo(array[j+1])>0){
                    swap(array,j+1,j);
                    swapped = true; // 标记已进行交换
                }
            }
            // 如果一轮比较下来没有进行过交换,说明数组已经有序,可以提前结束
            if (!swapped) break;

        }
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RH 414膜电位荧光探针,161433-30-3,具有出色的荧光性质和高度专业化的反应原理

一、试剂信息 名称&#xff1a;RH 414膜电位荧光探针CAS号&#xff1a;161433-30-3结构式&#xff1a; 二、试剂内容 RH 414膜电位荧光探针是一种基于荧光共振能量转移&#xff08;FRET&#xff09;技术的荧光染料&#xff0c;具有出色的荧光性质和高度专业化的反应原理。…

Cordova 12 Android 不支持 http 原因探索

最近在升级 Cordova 到最新版本&#xff0c;升级完成后发现无法请求网络&#xff0c;研究了两次最终发现解决方案。 发现控制台中有日志输出&#xff0c;提示当前是 https &#xff0c;无法直接访问 http。 [INFO:CONSOLE(225)] "Mixed Content: The page at https://lo…

如何更好地使用Kafka? - 运行监控篇

要确保Kafka在使用过程中的稳定性&#xff0c;需要从kafka在业务中的使用周期进行依次保障。主要可以分为&#xff1a;事先预防&#xff08;通过规范的使用、开发&#xff0c;预防问题产生&#xff09;、运行时监控&#xff08;保障集群稳定&#xff0c;出问题能及时发现&#…

tf2使用savemodel保存之后转化为onnx适合进行om模型部署

tf2使用savemodel保存之后转化为onnx适合进行om模型部署 tf保存为kears框架h5文件将h5转化为savemodel格式&#xff0c;方便部署查看模型架构将savemodel转化为onnx格式使用netrononnx模型细微处理代码转化为om以及推理代码&#xff0c;要么使用midstudio tf保存为kears框架h5文…

设计严谨,思路绝妙!这篇高级孟德尔随机化研究:药靶、共定位,发文一区(IF=8.9)!...

现在越来越多的学者在用孟德尔随机化高级方法发文&#xff0c;今天我们看的这篇这篇药靶孟德尔随机化&#xff0c;还用了共定位分析方法&#xff0c;亮点在于它的设计严谨&#xff0c;思路绝妙&#xff0c;一起看下去吧&#xff01; 2024年4月21日&#xff0c;四川大学华西医院…

机器人码垛机的主体结构及技术特点

在现代物流和生产线上&#xff0c;机器人码垛机以其高效、准确的特点&#xff0c;成为了不可或缺的重要设备。那么&#xff0c;这个神奇的机器人究竟由哪些部分组成?它的内部结构又有哪些奥秘呢?接下来&#xff0c;就让我们一起揭开它的神秘面纱! 一、机器人码垛机的主体结构…

每日OJ题_贪心算法三②_力扣553. 最优除法

目录 力扣553. 最优除法 解析代码 力扣553. 最优除法 553. 最优除法 难度 中等 给定一正整数数组 nums&#xff0c;nums 中的相邻整数将进行浮点除法。例如&#xff0c; [2,3,4] -> 2 / 3 / 4 。 例如&#xff0c;nums [2,3,4]&#xff0c;我们将求表达式的值 "…

【Leetcode每日一题】 穷举vs暴搜vs深搜vs回溯vs剪枝_全排列 - 子集(解法2)(难度⭐⭐)(72)

1. 题目解析 题目链接&#xff1a;78. 子集 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 为了生成一个给定数组 nums 的所有子集&#xff0c;我们可以利用一种称为回溯&#xff08;backtracking&#xff09;的算法…

美国纽扣电池UL4200A及16CFR1262标准亚马逊要求

2023年9月21日&#xff0c;美国消费品安全委员会CPSC(Consumer Product Safety Commission) 决定采用UL 4200A-2023&#xff08;包含纽扣电池或硬币电池的产品安全标准&#xff09;作为包含纽扣电池或硬币电池的消费品的强制性消费品安全规则&#xff0c;相关要求同时被编入到1…

C++中的异常处理方式

目录 一、异常 二、C语言中对错误的处理 三、C中的异常处理 四、异常的抛出和捕获 五、异常的重新抛出 六、C标准库中的异常体系 七、异常的规范 一、异常 在C中&#xff0c;异常是程序运行期间发生的意外或错误情况。这些情况可能会导致程序无法继续正常执行&#xff0c;…

STM32接入CH340芯片的初始化进入升级模式(死机)问题处理

目录 1. 问题描述2. 问题分析2.1 CH340G/K 的初始化波形2.2 第1种USB升级电路2.3 第2种USB升级电路2.4 第3种USB升级电路2.5 第4种USB升级电路 3. 总结 1. 问题描述 我所用的CH340G&#xff08;CH340K也用过&#xff09;接在MCU的电路中&#xff0c;在插入CH340G/K 的接插件&a…

基于点灯Blinker的ESP8266远程网络遥控LED

本文介绍基于ESP8266模块实现的远程点灯操作&#xff0c;手机侧APP选用的是点灯-Blinker&#xff0c;完整资料及软件见文末链接 一、ESP8266模块简介 ESP8266是智能家居等物联网场景下常用的数传模块&#xff0c;具有强大的功能&#xff0c;通过串口转WIFI的方式可实现远距离…

文献速递:深度学习医学影像心脏疾病检测与诊断--CT中的深度学习用于自动钙评分:使用多个心脏CT和胸部CT协议的验证

Title 题目 Deep Learning for Automatic Calcium Scoring in CT: Validation Using Multiple Cardiac CT and Chest CT Protocols CT中的深度学习用于自动钙评分&#xff1a;使用多个心脏CT和胸部CT协议的验证 Background 背景 Although several deep learning (DL) calc…

微软开发新模型;YouTube 推出新AI功能;可折叠iPhone 或发布?

微软或开发新模型与 Google、OpenAI 竞争 The Information 报道&#xff0c;微软正在训练一种新的 AI 大模型「MAI-1」&#xff0c;规模上足以与 Google、Anthropic 乃至 OpenAI 的先进模型抗衡。 据报道&#xff0c;这个 MAI-1 模型由微软聘请的 Inflection 前 CEO Mustafa S…

unity基础(二)

debug方法 Debug.Log(" 一般日志 ");Debug.LogWarning(" 警告日志 ");Debug.LogError(" 错误日志 ");// Player Informationstring strPlayerName "Peter";int iPlayerHpValue 32500;short shPlayerLevel 10;long lAdvantureExp 1…

爱普生MCU系列语音芯片S1C31D41

随着科技的发展和产品的集成化&#xff0c;语音芯片已经逐渐替代了多种语音设备应用在各场合。语音芯片主要特性是功耗低&#xff0c;抗干扰能力强&#xff0c;外围器件少&#xff0c;控制简单&#xff0c;语音保存时间久(某些语音芯片可以保存内容100年)&#xff0c;掉电不丢失…

yolo-world:”目标检测届大模型“

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

【Git】Git学习-16:git merge,且解决合并冲突

学习视频链接&#xff1a; 【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 1 创建分支dev&#xff0c;并用merge合并master分支&#xff0c;使dev分支合并上master分支中内容为…

[Algorithm][多源BFS][矩阵][飞地的数量][地图中的最高点][地图分析] + 多源BFS原理讲解 详细讲解

目录 0.原理讲解1.矩阵1.题目链接2.算法原理详解3.代码实现 2.飞地的数量1.题目链接2.算法原理详解3.代码实现 3.地图中的最高点1.题目链接2.算法原理详解3.代码实现 4.地图分析1.题目链接2.算法原理详解3.代码实现 0.原理讲解 注意&#xff1a;只要是用**BFS解决的最短路径问题…

韩顺平0基础学Java——第5天

p72——p86 今天同学跟我说别学java&#xff0c;真的吗&#xff1f;唉&#xff0c;先把这视频干完吧。 逻辑运算符练习 x6&#xff0c;y6 x6&#xff0c;y5 x11&#xff0c;y6 x11&#xff0c;y5 z48 错了&a…
最新文章