排序算法-冒泡排序

news2025/1/24 2:25:21

基本思路

遍历给定的数组,从左往右,两两比较,小的放在左边,大的放在右边,遍历完成,数组有序。

先来看一个冒泡排序的过程:

给定数组:[5,3,2,1,4]

排序结果:[1,2,3,4,5]

拆解步骤

1.第一轮从左往右循环,遍历前5个数:

(1) 来到5和3,5大于3  ==>  5和3交换 

 

(2) 来到5和2,5大于2 ==> 5和2交换

 (3) 来到5和1,5大于1 ==> 5和1交换

 (4) 来到5和4,5大于4 ==> 5和4交换

 第一轮遍历结束,最右侧的5是数组中最大的,不用动了。

 

2.第二轮从左往右循环,遍历前4个数

 (1) 来到3和2,3大于2 ==> 3和2交换

(2) 来到3和1,3大于1 ==> 3和1做交换 

 

 (3) 来到3和4,3小于4 ==> 不用交换

第二轮遍历结束,最右侧的4已经是待排序数中最大的,不用动。

……略

得出规律

依次类推,得出规律:

1.每一次遍历的都是左侧待排序的数,遍历完成后会将最大的数放到最右边。

2.一共需要数组长度次数的遍历,比如数组长度是5,就需要5次遍历。

代码实现

public class BubbleSort {

    public static void main(String[] args) {
        int[] arr = {5, 3, 2, 1, 4};
        for (int i : arr) {
            System.out.print(i);
            System.out.print(" ");
        }
        System.out.println();
        bubbleSort(arr);
        System.out.println("冒泡排序后 ---->");
        for (int i : arr) {
            System.out.print(i);
            System.out.print(" ");
        }
    }

    /**
     * 冒泡排序
     *
     * @param arr 待排序的数组
     */
    public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {  // 数组长度是多少,就需要遍历多少次数组
            for (int j = 0; j < arr.length - i - 1; j++) { // 每次遍历的范围是 0 ~ len-i-1
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }
        }
    }

    /**
     * 数组交换
     *
     * @param arr    数组
     * @param index1 下标1
     * @param index2 下标2
     */
    public static void swap(int[] arr, int index1, int index2) {
        arr[index1] = arr[index1] + arr[index2];
        arr[index2] = arr[index1] - arr[index2];
        arr[index1] = arr[index1] - arr[index2];
    }
}

对数器验证

import cn.hutool.core.util.RandomUtil;
import java.util.Arrays;
public class BubbleSortTest {

    public static void main(String[] args) {
        int[] arr1 = new int[1000];
        for (int i = 0; i < arr1.length; i++) {
            arr1[i] = RandomUtil.randomInt(0, 10000);
        }
        final int[] arr2 = Arrays.copyOf(arr1, arr1.length);
        System.out.println("拷贝的数组arr2是否等于arr1:" + equals(arr1, arr2));
        print(arr1);
        Arrays.sort(arr1);
        System.out.println("使用系统的排序算法排序后的数组 ------->");
        print(arr1);
        BubbleSort.bubbleSort(arr2);
        System.out.println("使用冒泡排序算法排序后的数组 ------->");
        print(arr2);
        System.out.println("冒泡排序算法结果与系统内置排序算法结果是否一致:" + equals(arr1, arr2));
    }

    public static void print(int[] arr){
        for (int i : arr) {
            System.out.print(i);
            System.out.print(" ");
        }
        System.out.println();
    }

    public static boolean equals(int[] arr1, int[] arr2){
        if(arr1 == null && arr2 == null){
            return true;
        }
        if(arr1 == null || arr2 == null){
            return false;
        }
        if(arr1.length != arr2.length){
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if(arr1[i] != arr2[i]){
                return false;
            }
        }
        return true;
    }

}

 优化

思路:如果在一次遍历中,发现所有的元素都不需要交换,那么说明这个数组已经是有序数组了。

比如一个数组:[1,2,3,4,5],其冒泡排序过程如下:

 

 对于这种有序数组,其实只需要遍历一次就可以了。我们可以在每次循环的时候记录当前循环是否发生了交换操作,如果没有发生,就提前结束排序操作,因为数组已经是有序了。

需要优化的核心代码:

/**
 * 冒泡排序
 *
 * @param arr 待排序的数组
 */
public static void bubbleSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }
    for (int i = 0; i < arr.length; i++) {  // 数组长度是多少,就需要遍历多少次数组
        boolean swaped = false; // 用来记录是否交换的变量
        for (int j = 0; j < arr.length - i - 1; j++) { // 每次遍历的范围是 0 ~ len-i-1
            if (arr[j] > arr[j + 1]) {
                swaped = true; // 如果发生了交换,就记为true
                swap(arr, j, j + 1);
            }
        }
        if(!swaped){
            // 如果一次交换都没有发生,就是数组已经有序了
            return;
        }
    }
}

其他定论

1.冒泡排序在排序期间没有申请其他的内存空间,它的空间复杂度是O(1),所以是原地排序算法

2.冒泡排序对于相同数值的元素来说,每次排序后所在的位置不变,因此冒泡排序是稳定的排序算法

3.冒泡排序的时间复杂度是O(n^2)

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

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

相关文章

Sha1,Sha256 哈希(摘要)处理

具体参考&#xff1a;Sha1,Sha256哈希&#xff08;摘要&#xff09;在线处理工具

显示今天的年、月、日日期、时间的数据处理timetuple()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 显示今天的年、月、日 日期、时间的数据处理 timetuple() [太阳]选择题 对下面描述错误的选项为&#xff1f; import datetime dtdatetime.date.today() print("【显示】dt",dt) p…

Redis最全详解(三)——SpringBoot整合2种方式

SpringBoot整合Redis 常用 api 介绍 有两个 redis 模板&#xff1a;RedisTemplate 和 StringRedisTemplate。我们不使用 RedisTemplate&#xff0c;RedisTemplate 提供给我们操作对象&#xff0c;操作对象的时候&#xff0c;我们通常是以 json 格式存储&#xff0c;但在存储的…

[附源码]java毕业设计作业自动评阅系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【window下配置Maxim SDK环境】

【window下配置Maxim SDK环境】1. 前言2. Maxim SDK下载3. Maxim SDK安装3.1 安装详解3.2 安装完成4. 测试环境4.1 新建Hello word demo4.2 编译调试下载4.2.1 clean4.2.2 build4.2.3 Openocd5. 实验效果6.小结1. 前言 MAX78000FTHR为快速开发平台&#xff0c;帮助工程师利用M…

第149篇 笔记-web3

定义&#xff1a;Web3是基于去中心化原则的互联网新革命。Web3将当今丰富的交互式数字体验与为用户提供所有权和加密保证的基础设施相结合。 最近在传统技术部门和区块链生态系统的行业领导者中&#xff0c;Web3已成为主流意识&#xff0c;其对互联网的过去和未来有着广泛的影…

蜂鸟E203学习笔记(三)——流水线结构

握手和反压 首先介绍握手协议 valid-ready握手协议 valid先发起请求 ready先发出请求 同时发出请求 仔细观察上述3幅时序图&#xff0c;我们了解valid-ready握手机制需要注意三件事&#xff1a; valid与ready不可过度依赖&#xff0c;比如valid不可以等待ready到达再拉高&…

设计模式之工厂模式

文章目录1.前言工厂模式的三种实现方式应用场景2.简单工厂模式核心组成实现UML类图优点与缺点3.工厂方法模式核心组成实现UML类图优点与缺点4.抽象工厂模式核心组成实现UML类图优点与缺点1.前言 在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;…

React - Ant Design4.x版本安装使用,并按需引入和自定义主题

React - Ant Design4.x版本安装使用&#xff0c;并按需引入和自定义主题一. 安装使用 antd二&#xff0e;antd 高级配置安装 craco&#xff0c;对 create-react-app 的默认配置进行自定义自定义主题安装 babel-plugin-import &#xff0c;按需加载组件代码和样式Ant Design官网…

备赛笔记:RCNN网络基础

1 目标检测&#xff1a; 目标检测指的是对目标进行分类与定位&#xff0c;输入图片&#xff0c;输出物体类别以及其坐标 目标检测模型分为one stage 和two stage类型。one stage及端到端&#xff0c;速度较快&#xff0c;但是准确性较差&#xff0c;two stage网络速度较慢&…

CDH5.12.0-HiveServer2-java.net.SocketTimeoutException: Read timed out

问题描述 环境&#xff1a; 开发调度平台&#xff1a;数栖平台4.18&#xff08;16000任务&#xff0c;7000工作流&#xff09;大数据平台&#xff1a;CDH 5.12.0&#xff0c;大数据组件默认版本BI工具&#xff1a;FineBI实时数仓&#xff1a;Dolphinscheduler StarRocks 问…

从核酸检测平台崩盘看性能工程的范围

近几年疫情肆虐&#xff0c;健康码系统和核酸检测系统成了民生的保障。在疫情张狂的时候&#xff0c;这类系统的稳定性、可用性是关键的技术支撑能力。 每个地方的健康码平台都或多或少地出现过问题&#xff0c;影响每个人的生活。 从我工作十几年的性能工作经验&#xff0c;来…

225. 用队列实现栈-C语言

题目来源&#xff1a;力扣 题目描述&#xff1a; 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压…

Python爬取数据分析

一.python爬虫使用的模块 1.import requests 2.from bs4 import BeautifulSoup 3.pandas 数据分析高级接口模块 二. 爬取数据在第一个请求中时, 使用BeautifulSoup   import requests # 引用requests库 from bs4 import BeautifulSoup # 引用BeautifulSoup库 res_movies re…

pycharm Process finished with exit code: -1073741571

问题现象 在pycharm使用debug模式调试代码时&#xff0c;异常退出&#xff0c;且错误码为-1073741571。除了错误码外&#xff0c;并没有看到其它报错。 分析 查阅资料&#xff1a; Process finished with exit code -1073741571 (0xC00000FD) when trying to implement ab…

ZPM介绍(3)

建立私服(Porxy-Registry) 这张图解释了您的私服是怎么工作的&#xff0c; 整篇文章在这里&#xff1a; Proxy-Registry 搭建私服 您需要有一台自己的的服务器&#xff0c; 在上面安装IRIS, zpm, 然后用zpm去下载另一个软件包“zpm-registry"。象这样 zpm:DEMO>search …

如何设置子域名?

什么叫子域名 域名可以划分为各个子域&#xff0c;子域还可以继续划分为子域的子域&#xff0c;这样就形成了顶级域、主域名、子域名等。 举例&#xff1a; “.com”是顶级域名&#xff08;一级域名&#xff09;&#xff1b; “aliyun.com”是主域名&#xff08;二级域名&…

AtCoder Beginner Contest 264 G.String Fair(最短路/暴力dp 补写法)

题目 n(n<18278)个串&#xff0c;第i个串Ti(Ti为纯小写字母串且长度不超过3)&#xff0c; 得分Pi(-1e9<Pi<1e9)&#xff0c;表示只要子串中出现一次Ti&#xff0c;就会获得Pi的得分 对于你可以构造的无限长的串S来说&#xff0c;S的最终得分&#xff0c;为其中每一…

我参加第七届NVIDIA Sky Hackathon——训练CV模型

如何从0开始训练自己的CV模型 第一步 配置基本环境(在上一篇已经配置了我参加第七届NVIDIA Sky Hackathon——训练ASR模型 ) 第二步 利用labelimg制作图像数据集 第三步 开始训练resnet18模型 文章目录如何从0开始训练自己的CV模型前言一、利用labelimg制作图像数据集1.安装la…

JetPack之LifeCycle设计模式与解耦艺术的极致运用

在研发过程中&#xff0c;解耦是一个永恒的话题。因为解耦可以为后续的维护、功能添加、防内存泄漏、问题查找及更新都带来便利且做到影响最小&#xff0c;但如何进行解耦设计却是一门艺术。今天&#xff0c;我们就来看看google工程师是如何设计LifeCycle的。 我们在很多时候都…