每日一算-冒泡排序

news2024/12/27 13:53:49

冒泡排序是最简单的排序算法,如果相邻元素的顺序错误,则通过重复交换它们来工作。该算法不适用于大数据集,因为它的平均和最坏情况时间复杂度都很高。

原理

alt

输入: arr[] = {6, 3, 0, 5}

第一步:

  • 冒泡排序从最前面的两个元素开始,比较它们以检查哪个更大。
  • ( 6 3 0 5 ) –> ( 3 6 0 5 ),这里,算法比较前两个元素,并从 6 > 3 开始交换。
  • ( 3 6 0 5 ) –> ( 3 0 6 5 ), 从 6 > 0 开始交换
  • ( 3 0 6 5 ) –> ( 3 0 5 6 ), Swap since 6 > 5

第二步:

  • 现在,在第二次迭代期间,它应该如下所示:
  • ( 3 0 5 6 ) –> ( 0 3 5 6 ), Swap since 3 > 0
  • ( 0 3 5 6 ) –> ( 0 3 5 6 ), 不变为 5 > 3

第三步:

  • 现在,数组已经排序了,但是我们的算法不知道它是否完成了。

  • 该算法需要一个

    完整的传递,而不进行任何交换才能知道它已排序。

  • ( 0 3 5 6 ) –> ( 0 3 5 6 ), 没有变化 3 > 0

数组现在已排序,不会再发生传递。

算法实战

请按照以下步骤解决问题:

  • 运行嵌套的 for 循环以使用两个变量 ij遍历输入数组,使得 0 ≤ i < n-1 和 0 ≤ j < ni-1
  • 如果**arr[j] 大于arr[j+1]**则交换这些相邻元素,否则继续
  • 打印排序后的数组

下面是上述方法的实现:

  • Java版本
import java.util.*;

class BubbleSort {
 void bubbleSort(int arr[])
 {
  int n = arr.length;
  for (int i = 0; i < n - 1; i++)
   for (int j = 0; j < n - i - 1; j++)
    if (arr[j] > arr[j + 1]) {
     // swap arr[j+1] and arr[j]
     int temp = arr[j];
     arr[j] = arr[j + 1];
     arr[j + 1] = temp;
    }
 }


 void printArray(int arr[])
 {
  int n = arr.length;
  for (int i = 0; i < n; ++i)
   System.out.print(arr[i] + " ");
  System.out.println();
 }

 
 public static void main(String args[])
 {
  BubbleSort ob = new BubbleSort();
  int arr[] = { 5, 1, 4, 2, 8 };
  ob.bubbleSort(arr);
  System.out.println("Sorted array");
  ob.printArray(arr);
 }
}

输出

排序数组:
1 2 4 5 8

时间复杂度: O(N 2 ) 辅助空间: O(1)

冒泡排序的优化实现:

即使数组已排序,上述函数也始终运行O(N 2 )时间。如果内部循环没有引起任何交换,可以通过停止算法来优化它。

下面是上述方法的实现:

  • Java版本实现
import java.io.*;

class GFG
{
 // 冒泡排序的优化版本
 static void bubbleSort(int arr[], int n)
 {
  int i, j, temp;
  boolean swapped;
  for (i = 0; i < n - 1; i++)
  {
   swapped = false;
   for (j = 0; j < n - i - 1; j++)
   {
    if (arr[j] > arr[j + 1])
    {
     // swap arr[j] and arr[j+1]
     temp = arr[j];
     arr[j] = arr[j + 1];
     arr[j + 1] = temp;
     swapped = true;
    }
   }

   // 如果内循环没有交换任何两个元素,那么就跳出循环。
   if (swapped == false)
    break;
  }
 }

 
 static void printArray(int arr[], int size)
 {
  int i;
  for (i = 0; i < size; i++)
   System.out.print(arr[i] + " ");
  System.out.println();
 }


 public static void main(String args[])
 {
  int arr[] = { 64, 34, 25, 12, 22, 11, 90 };
  int n = arr.length;
  bubbleSort(arr, n);
  System.out.println("Sorted array: ");
  printArray(arr, n);
 }
}

输出

排序数组:
11 12 22 25 34 64 90

时间复杂度: O(N 2 ) 辅助空间: O(1)

冒泡排序的最坏情况分析:

冒泡排序的最坏情况发生在数组元素按降序排列时。 在最坏的情况下,对给定数组进行排序所需的迭代或遍历总数为**(n-1)。**其中“n”是数组中存在的元素数量。

在第 1 遍: 比较次数 = (n-1) 交换次数 = (n-1)

在第 2 遍: 比较次数 = (n-2) 交换次数 = (n-2)

在第 3 遍: 比较次数 = (n-3) 交换次数 = (n-3) . . 在第 n-1 次: 比较次数 = 1 交换次数 = 1

现在,计算排序数组所需的比较总数 = (n-1) + (n-2) + (n-3) + 。. . 2 + 1 = (n-1)*(n-1+1)/2 { 用N个自然数求和公式} = n (n-1)/2

对于最坏的情况:

交换总数 = 比较总数 比较 总数(最坏情况)= n(n-1)/2 交换总数(最坏情况)= n(n-1)/2

最坏和平均情况时间复杂度: O(N 2 )。最坏的情况发生在数组被反向排序时。 最佳情况时间复杂度: O(N)。最好的情况发生在数组已经排序时。 辅助空间: O(1)

冒泡排序的递归实现:

这个想法是将最大的元素放在它的位置上,并对所有其他元素继续做同样的事情。

算法:

  1. 从一组未排序的数字开始
  2. 定义一个名为“ bubbleSort ”的函数,它将数组和数组的长度作为参数
  3. 在函数中,创建一个名为“ sorted ”的变量,并将其设置为 true
  4. 创建一个 for 循环,遍历从索引 0开始到数组长度**-1结束的数组**
  5. 在 for 循环中,将当前元素与数组中的下一个元素进行比较
  6. 如果当前元素大于下一个元素,交换它们的位置并将“ sorted ”设置为false
  7. for循环后,检查“ sorted ”是否为假
  8. 如果“ sorted ”为假,以相同的数组和长度作为参数再次调用“ bubbleSort ”函数
  9. 如果“ sorted ”为真,则数组现在已排序,函数将返回排序后的数组
  10. 使用初始未排序数组及其长度作为参数调用“ bubbleSort ”函数以开始排序过程。

下面是上述方法的实现:

  • Java版本
import java.util.*;
class GFG
{
 public static void main(String[] args) {
  
  int[] ar={5,4,8,2,9,7,3};
  bubbleSort(ar,ar.length);
  
  System.out.print("Sorted array : ");
  for(int ele:ar)
  {
   System.out.print(ele+" ");
  }
  System.out.println();
  
 }
 public static void bubbleSort(int[] a,int n)
 {
  boolean sorted=true;
 //我们假设该数组已经排序。
  
  for(int i=0;i<n-1;i++)
  {
   if(a[i]>a[i+1])
   {
    int t=a[i];
    a[i]=a[i+1];
    a[i+1]=t;
    
    sorted=false;
   //现在数组没有排序。
   }
  //如果没有交换,那么我们可以说数组已经排序。
   
  }
  if(sorted==false)
  {
   //递归调用直到它被排序。
   bubbleSort(a,n);
  }
 }
}

输出

排序数组:2 3 4 5 7 8 9

时间复杂度O (N 2 )

辅助空间O(1)

冒泡排序的边界情况是什么?

当元素已经排序时,冒泡排序需要最短时间(n 的顺序)。因此最好事先检查数组是否已经排序,以避免 O(N 2 ) 时间复杂度。

排序是否在冒泡排序中发生?

是的,冒泡排序在不使用任何主要数据结构的情况下执行相邻对的交换。因此冒泡排序算法是一种就地算法。

冒泡排序算法稳定吗?

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

冒泡排序算法用在哪里?

由于其简单性,冒泡排序通常用于介绍排序算法的概念。 在计算机图形学中,它因其能够检测几乎已排序的数组中的微小错误(如仅交换两个元素)并仅以线性 复杂度 (2n) 修复它而广受欢迎。

示例:它用于多边形填充算法,其中边界线按特定扫描线(平行于 x 轴的线)的 x 坐标排序,并且随着 y 的递增,它们的顺序仅发生变化(交换两个元素)在两条线的交叉点(来源:维基百科)

优点:

  • 冒泡排序易于理解和实现。
  • 它不需要任何额外的内存空间。
  • 它对不同类型的数据具有适应性。
  • 它是一种稳定的排序算法,意味着具有相同键值的元素在排序后的输出中保持它们的相对顺序。

缺点

  • 冒泡排序的时间复杂度为 O(n^2),这使得它对于大型数据集非常慢。
  • 它对于大型数据集效率不高,因为它需要多次遍历数据。
  • 冒泡排序是一种基于比较的排序算法,这意味着它需要一个比较运算符来确定输入数据集中元素的相对顺序。虽然这不一定是缺点,但在某些情况下它会限制算法的效率。

本文由 mdnice 多平台发布

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

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

相关文章

每日一算-选择排序算法

大家好&#xff0c;我是易安&#xff01; 今天我们开始每日一算的篇章&#xff0c;今天带来的是选择算法。 选择排序是一种简单而高效的排序算法&#xff0c;它通过从列表的未排序部分中重复选择最小&#xff08;或最大&#xff09;元素并将其移动到列表的已排序部分来工作。该…

Kubernetes集群安全加固

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130678814 一、系统账户加固 1、对账户的登录次数进行检查&#xff0c;连续超过3次登录失败后&#xff0c;对用户锁定150s # 每个设备上都运行 sed -i~ 2iauth required pam_faillock.so deny3 unloc…

玩转Google开源C++单元测试框架Google Test系列(gtest)之五 - 死亡测试

一、前言 “死亡测试”名字比较恐怖&#xff0c;这里的“死亡”指的的是程序的崩溃。通常在测试过程中&#xff0c;我们需要考虑各种各样的输入&#xff0c;有的输入可能直接导致程序崩溃&#xff0c;这时我们就需要检查程序是否按照预期的方式挂掉&#xff0c;这也就是所谓的…

CBFS Shell .NET 22.0.85 Crack

使用虚拟文件夹、自定义菜单、工具栏、详细信息列等扩展和自定义 Windows 资源管理器&#xff01; CBFS Shell 窗口资源管理器自定义 使用 CBFS Shell 为您的用户扩展 Windows 资源管理器。定义用户如何与文件和文件夹交互、自定义上下文菜单、添加信息列等。与可能导致资源管…

详细解释什么是LNMP架构

LNMP(Linux-Nginx-MySQL-PHP)是一种常见的Web服务器架构&#xff0c;适用于中小型网站和应用。 它包括四个核心组件&#xff1a; 1. Linux:LNMP架构是在Linux操作系统上运行的。通常选择Ubuntu、Debian等基于Debian的发行版作为Linux系统。 2. Nginx:Nginx是一个高性能的Web服…

支付系统设计三:支付网关设计09-总结

文章目录 前言一、设计目标二、设计实现1. 开发框架2. 配置管理后台3. 屏蔽渠道差异4. 各阶段工作内容4.1 业务处理前期准备阶段4.2 业务处理阶段4.2.1 交易处理模板获取4.2.2 参数验证4.2.3 幂等性验证4.2.4 交易数据准备服务获取4.2.5 路由处理4.2.6 支付渠道数据补全4.2.7 交…

Docker高级(完结)

一、DockerFile DockerFile简介 Docker是用来构建Docker镜像文件&#xff0c;由一条条docker指令和参数构成的脚本。 DockerFile构建过程 小总结 从应用软件的角度来看&#xff0c;Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段&#xff0c; Dockerfile是…

浅析垃圾回收

大家好&#xff0c;我是易安&#xff01; Java虚拟机的自动内存管理&#xff0c;将原本需要由开发人员手动回收的内存&#xff0c;交给垃圾回收器来自动回收。不过既然是自动机制&#xff0c;肯定没法做到像手动回收那般精准高效 &#xff0c;而且还会带来不少与垃圾回收实现相…

《MongoDB入门教程》 - MongoDB基础介绍

前言 时间也过太快了嘛&#xff0c;一晃上次更新都又过去6个月了&#xff0c;再不更新就变成年更博客了。 对了&#xff0c;第一次疫情也过去了&#xff0c;最近开始二阳了&#xff0c;希望大家能继续挺过去吧 本篇文章初尝试使用ChatGPT进行&#xff0c;博主主要负责排版和总…

mysql使用xtrabackup方式复制过滤某一个数据库

需求&#xff1a; 搭建一个新的从库&#xff0c;只复制过滤源端数据库里的其中一个数据库workflow到新实例上。 一 操作步骤 1.1 在目标端新建一个数据库实例 略 1.2 在源端做备份 /home/urman-agent/bin/xtrabackup --defaults-file/data/mysql/etc/13314/my.cnf --targ…

redis缓存穿透、缓存击穿、缓存雪崩

一、缓存 缓存是数据交换的缓冲区&#xff0c;是存储数据的临时地方&#xff0c;一般读写性能较高。 如浏览器会把静态资源先加载到浏览器缓存中&#xff0c;tomcat中有应用层缓存等&#xff0c;则数据库也有数据库缓存。 缓存的作用&#xff1a; 降低后端负载提高读写效率…

ES8基本命令

ElasticSearch是面向文档型数据库 构造类似于数据库&#xff1a;indexes(索引库数据库)-->types(类型表)-->documents(文档行)-->field(字段字段) 但是在7.X开始&#xff0c;Type已经开始被废弃。 正排索引&#xff1a;根据主键id关联内容&#xff0c;然后再找关键字…

微服务—Redis实用篇-黑马头条项目-达人探店功能(使用set与zset实现)

微服务—Redis实用篇-黑马头条项目-达人探店功能(使用set与zset实现) 1、达人探店 1.1、达人探店-发布探店笔记 发布探店笔记 探店笔记类似点评网站的评价&#xff0c;往往是图文结合。对应的表有两个&#xff1a; tb_blog&#xff1a;探店笔记表&#xff0c;包含笔记中的标…

Liunx基础命令 - mkdir命令

mkdir命令 – 创建目录文件 mkdir命令来自英文词组”make directories“的缩写&#xff0c;其功能是用来创建目录文件。使用方法简单&#xff0c;但需要注意若要创建的目标目录已经存在&#xff0c;则会提示已存在而不继续创建&#xff0c;不覆盖已有文件。而目录不存在&#…

路径规划算法:基于蜉蝣优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于蜉蝣优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蜉蝣优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法蜉蝣…

Linux 无网环境下离线安装rpm

概述 搭建了私有yum仓库&#xff0c;想实现无网环境下Docker rpm离线安装的方法 1. 使用和配置清华源 2. 免安装下载rpm包及其依赖 3. 寻找特定的rpm包并补全依赖 清华的清华源 名称连接帮助文档备注主页清华大学开源软件镜像站 | Tsinghua Open Source MirrorAOSP | 镜像站使…

Swagger 3.0 与 Springboot 集成

springboot版本:2.3.12.RELEASE swagger版本:3.0.0 1&#xff1a;pom文件添加如下代码: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version>&…

离线安装 Docker + Docker registry(Docker仓库)

概述 通过私有yum仓库安装docker 具体内容&#xff1a; 1. 构建私有镜像仓库 2. 准备rpm包 3. 安装部署 4. ansible 安装 卸载 5. shell 脚本安装 卸载 6. 网页连接 7. 构建docker 私有仓库 1. 构建私有镜像仓库 构建简单的yum私有仓库请参考如下文档 http://t.csdn.cn/22bmb…

用chatGPT写chatGPT教学方案

最近从机器学习的原理、数学推理、主流模型架构、chatGPT的Prompt策略&#xff0c;也实际体验了各种AIGC工具&#xff0c;算是较为系统的学习了chatGPT的前世今身&#xff0c;想着有很多人应该跟我一样&#xff0c;没有编程基础、也没有成为chatGPT专家的希望&#xff0c;仅仅通…

LeetCode_Day3 | 反转链表/移除链表的元素/设计个链表

LeetCode_链表 203.移除链表元素1. 题目描述2. 直接使用原表删除1. 思路2. 代码实现 3. 使用虚拟头节点删除1. 思路2. 代码实现 707.设计链表1.题目描述2.单链表&#xff1a;虚拟头节点设计1. 思路2. 代码实现及部分逻辑解释3. 需要注意的点 206.反转链表1.题目描述2. 双指针法…