冒泡排序详解

news2024/10/3 8:27:36

冒泡排序是初学C语言的噩梦,也是数据结构中排序的重要组成部分,本章内容我们一起探讨冒泡排序,从理论到代码实现,一步步深入了解冒泡排序。

排序算法作为较简单的算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

算法步骤

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

动图演示

可能大家对文字描述不敏感,但是这副图完美的呈现了冒泡排序的实现过程。

本图来源于网络

时间复杂度

什么时候最快

这点不用想,当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊)。

什么时候最慢

这个就与上文相对应,肯定是反序的时候最慢。

分析

最好情况是一次搞定,时间复杂度是O(N);

最坏的情况就是反序,时间复杂度是O(N^2);

平均情况,时间复杂度是O(N^2);

代码实现

代码实现原理图

我们先做一个交换函数

void Swap(int* p1, int* p2)
{
    int tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

实现代码:

我们先来一种常规的方法:

//冒泡函数
void Bubblesort(int* a, int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 1; j < n - i; j++)
        {
            if (a[j - 1] > a[j])
            {
                Swap(&a[j - 1], &a[j]);
            }
        }
    }
}

当然我们可以用”for“的方法实现,也可以用“while”的方法实现。

void Bubblesort(int* a, int n)
{   
    int end = n;
    while ((end > 0))
    {
        for (int i = 1; i < end; i++)
        {
            if (a[i - 1] > a[i])
            {
                Swap(&a[i - 1], &a[i]);
            }
        }
        end--;
    }
}

有些小伙伴可能会对两次“for”才能实现,初学者就会产生疑惑,为什么会这样,那我们可以先写一趟冒泡排序:

void Bubblesort(int* a, int n)
}
//一趟
      for (int i = 0; i < n - 1 - j; i++)
        {
            if (a[i] > a[i + 1])
            {
                Swap(&a[i], &a[i + 1]);
            }
        }
}

然后我们再来写整个冒泡排序

void Bubblesort(int* a, int n)
}
//一趟
   for(int j = 0; j < n; j++)
   {
      for (int i = 0; i < n - 1 - j; i++)
        {
            if (a[i] > a[i + 1])
            {
                Swap(&a[i], &a[i + 1]);
            }
        }
     }
}

看到这里我们有些小伙伴可能对总数是“n”还是“n-1”有些疑问。

其实这里,我们如果用仔细看可以发现,前者是以“j == 1”开始,后者是以“0”开始,所以造成了不同。

我们接着改一下,提升一下效率。我们想一下,假如我们在交换以后,接下来的数组已经是有序的了,那么我们就没必要交换了。

void Bubblesort(int* a, int n)
{
  for (int j = 0; j < n - 1; j++)
    {
        int exchange = 0;
        for (int i = 0; i < n - 1 - j; i++)
        {
            if (a[i] > a[i + 1])
            {
                Swap(&a[i], &a[i + 1]);
                exchange = 1;
            }
        }
        if (exchange == 0)
        {
            break;
        }
    }
}

这样我们就完成了

总结

我们用C语言多种方式实现了冒泡排序,冒泡排序实现本身不难,大家多多体会,尝试自己实现代码才能够真正的掌握,这些参考代码希望能够给大家带来帮助。

欢迎大家点赞和收藏。

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

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

相关文章

信道建模(大尺度、小尺度、莱斯衰落、瑞利衰落、莱斯信道、瑞利信道)

一、大尺度衰落与小尺度衰落 大尺度衰落由收发两端的距离决定&#xff0c;功率上建模为&#xff1a; 小尺度衰落由收发两端的环境决定&#xff0c;比如是否有遮挡&#xff0c;场景有室内、室外、平原、山村、城镇等&#xff0c;这些环境影响到收发两端是否有直达链路&#xff0…

电子电路中的各种接地(接地保护与GND)

前言多年以前&#xff0c;雷雨天气下&#xff0c;建筑会遭遇雷击&#xff0c;从而破坏建筑以及伤害建筑内的人&#xff0c;为了避免雷击的伤害&#xff0c;人们发明了避雷针&#xff0c;并将避雷针接地线&#xff0c;从而引导雷击产生的电流经过地线流入到地下。地线&#xff1…

传统目标检测实战:HOG+SVM

传统目标检测实战&#xff1a;HOGSVM 文章目录传统目标检测实战&#xff1a;HOGSVM1. 前言1.1 传统和深度1.2 何为传统目标检测1.3 传统目标检测方法不足2. 先验知识3. 项目框架3.1 文件架构3.2 方法简要介绍4. 工具函数&#xff08;utils.py&#xff09;5. 特征提取&#xff0…

我是如何转岗成为数据分析师?

Datawhale干货 作者&#xff1a;孟禹&#xff0c;数据分析师&#xff0c;Datawhale邀约作者笔者背景介绍&#xff1a;工作5年半&#xff0c;前4年在K12在线教育负责教研和用户转化&#xff0c;21年双减之后跳槽到一家新消费品牌公司做数据分析师&#xff0c;跨了行转了岗。现在…

领英LinkedIn的个人商务会员和企业销售会员我们应该怎么选?

在详细介绍领英LinkedIn会员之前先解释下为什么要开通。也就是领英免费用户会有哪些限制以至于我们需要付费去开通会员&#xff1a;1.有限的搜索次数使用免费的 LinkedIn 帐户&#xff0c;您将在一个月内搜索约 300 次后达到商业使用限制。一旦达到商业使用限制&#xff0c;您将…

SpringBoot学习笔记【part18】拦截器与文件上传

一、拦截器Interceptor 拦截器 Interceptor 多用于登录检查与静态资源放行场景。 拦截器的实现步骤 编写一个拦截器实现 HandlerInterceptor 接口 Slf4j public class LoginInterceptor implements HandlerInterceptor {/*** 目标方法执行之前*/Overridepublic boolean preHa…

Redis 分布式基础——主从复制其实挺简单

Redis 主从同步 redis-master-slave-index 一、主从复制是啥 主从复制&#xff0c;或者叫 主从同步&#xff0c;是指将一台 Redis 服务器的数据&#xff0c;复制到其他的 Redis 服务器。前者称为 主节点(master)&#xff0c;后者称为 从节点(slave)。且数据的复制是 单向 的&…

GitLab CI-CD 学习笔记

概述 1. CI/CD CI&#xff08;持续集成&#xff09;指开发人员一天内进行多次合并和提交代码操作&#xff0c;并通过自动化测试&#xff0c;完成构建 CD&#xff08;持续部署&#xff09;指每次代码更改都会自动部署到对应环境 CI/CD 结合在一起&#xff0c;可以加快开发团…

如何写出优雅的代码

最近在做代码审查时&#xff0c;发现一个问题&#xff0c;就是代码不够优雅。代码可以有bug&#xff0c;但不能不优雅&#xff0c;毕竟代码不只是运行程序&#xff0c;凡是需要维护的代码都是给人看的&#xff0c;你的代码风格侧面反映了你的编码习惯、思维逻辑和专业性。那么如…

【强化学习】马尔可夫决策过程MDP

1.马尔可夫决策过程MDP 1.1 MDP五元组 MDP<S,A,P,R,γ>MDP<\mathcal{S},\mathcal{A},\mathcal{P},\mathcal{R},\mathcal{\gamma}>MDP<S,A,P,R,γ>&#xff0c;其中&#xff1a; S\mathcal{S}S&#xff1a;状态空间A\mathcal{A}A&#xff1a;动作空间P\mathc…

【VictoriaMetrics】VictoriaMetrics单机版部署(二进制版)

1、下载安装包git路径,本文基于1.87.1版本 进入git地址 :https://github.com/VictoriaMetrics/VictoriaMetrics/tags 2、下载其中linux下的 amd64架构

【数据结构】单向链表的练习题

目录 前言 1、删除链表中等于给定值val的所有节点。 【题目描述】 【代码示例】 【 画图理解】 2、反转一个点链表 【题目描述】 【 代码思路】 【代码示例】 【画图理解】 3、给定一个带有头节点head的非空单链表&#xff0c;返回链表的中间节点&#xff0c;如果有两个…

三维重建——NeuralRecon项目源码解读

代码链接见文末 首先,需要指明的是NeuralRecon项目不支持windows,主要是使用到的例如torchsprase等不支持windows,您也可以在网上查找相应的替代方法。 1.数据与环境配置 ScanNet数据的获取首先需要向作者发送邮件,作者会回复一个下载的脚本,在提供的代码中,提供了…

Mysql数据库09——分组聚合函数

类似pandas里面的groupby函数&#xff0c;SQL里面的GROUP BY子句也是可以达到分组聚合的效果。 常用的聚合函数有COUNT(),SUM(),AVG(),MAX(),MIN()&#xff0c;其用法看名字都看的出来&#xff0c;下面一一介绍 聚合函数 COUNT()计数 统计student表中计科系学生的人数。 SE…

基于nodejs+vue疫情网课管理系统

疫情网课也都将通过计算机进行整体智能化操作,对于疫情网课管理系统所牵扯的管理及数据保存都是非常多的,例如管理员&#xff1a;首页、个人中心、学生管理、教师管理、班级管理、课程分类管理、课程表管理、课程信息管理、作业信息管理、请假信息管理、上课签到管理、论坛交流…

企业微信应用授权,第一次不授权手机号后如何再次开启

文章目录前言一、关于企业微信应用授权1、新建一个应用2、企业微信应用授权二、第一次拒绝后如何手动开启总结前言 简单记录一下&#xff1a; 最近做了几个企业微信应用授权web&#xff0c;和普通微信公众号授权差不多&#xff0c;记录一下 一、关于企业微信应用授权 1、新建…

失手删表删库,赶紧跑路?!

在数据资源日益宝贵的数字时代公司最怕什么&#xff1f;人还在&#xff0c;库没了是粮库、车库&#xff0c;还是小金库&#xff1f;实际上&#xff0c;这里的“库”是指的数据库Ta是公司各类信息的保险柜小到企业官网和客户信息大到金融机构的资产数据和国家秘密即便没有跟数据…

Linux服务器开发-2. Linux多进程开发

文章目录1. 进程概述1.1 程序概览1.2 进程概念1.3 单道、多道程序设计1.4 时间片1.5 并行与并发1.6 进程控制块&#xff08;PCB&#xff09;2. 进程的状态转换2.1 进程的状态2.2 进程相关命令查看进程实时显示进程动态杀死进程进程号和相关函数3. 进程的创建-fork函数3.1 进程创…

抖音线索信息自动汇总到SeaTable流程搭建示例

每当抖音有新意向用户添加时&#xff0c;往往被企业视为意向客户&#xff0c;常需要运营人员查看后同步到SeaTable表单系统进行汇总&#xff0c;但运营人员时常会遗忘&#xff0c;并且难免会遗漏掉部分信息&#xff0c;导致部分意向客户无人跟进&#xff0c;最终流失。 那么&a…

GO语音-切片使用的雷区与性能优化相关

文章目录前言一、切片是什么&#xff1f;二、切片使用注意项1.避免复制数组2.切片初始化3.切片GC三、切片使用注意什么1. 大家来思考一个代码示例&#xff1a;2. 修改切片的值3. 降低切片重复申请内存总结前言 在 Go 语言中&#xff0c;切片(slice)可能是使用最为频繁的数据结…