当前位置: 首页 > news >正文

排序算法:冒泡排序,golang实现

目录

前言

冒泡排序

代码示例

1. 算法包

2. 冒泡排序代码

3. 模拟排序

4. 运行程序

5. 从大到小排序

循环细节

外层循环

内层循环

总结

冒泡排序的适用场景

1. 数据量非常小

2. 数据几乎有序

3. 教学用途

4. 稳定性


前言

在实际场景中,选择合适的排序算法对于提高程序的效率和性能至关重要,本节课主要讲解"冒泡排序"的适用场景及代码实现。

冒泡排序

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

代码示例

下面我们使用Go语言实现一个冒泡排序:

1. 算法包

创建一个 pkg/algorithm.go 

mkdir pkg/algorithm.go

2. 冒泡排序代码

打开 pkg/algorithm.go 文件,代码如下

从小到大 排序

package pkg// BubbleSort 冒泡排序
func BubbleSort(arr []int) {n := len(arr)              // 获取切片长度for i := 0; i < n-1; i++ { // 外层循环控制遍历的次数for j := 0; j < n-i-1; j++ { // 内层循环控制每轮遍历的次数,每完成一轮,最大数就“冒泡”到最后if arr[j] > arr[j+1] { // 比较相邻元素,如果前一个比后一个大,则交换arr[j], arr[j+1] = arr[j+1], arr[j] // 两个元素换位置}}}
}

3. 模拟排序

打开 main.go 文件,代码如下:

package mainimport ("demo/pkg""fmt"
)func main() {// 定义一个切片,这里我们模拟 10 个元素arr := []int{999, 452, 37, 1573, 234, 5, 318, 76483, 115, 86}fmt.Println("Original data:", arr) // 先打印原始数据pkg.BubbleSort(arr)                // 调用冒泡排序fmt.Println("New data:  ", arr)    // 后打印排序后的数据
}

4. 运行程序

打开终端,我们运行 go :

go run main.go

能发现, Original data 后打印的数据,正是我们代码中定义的切片数据,顺序也是一致的。

New Data 后打印的数据,则是经过冒泡排序后的数据,是从小到大的。

5. 从大到小排序

如果需要 从大到小 排序也是可以的,在代码里,将两个元素比较的 大于符号 改成 小于符号 即可。

修改 pkg/algorithm.go 文件:

package pkg// BubbleSort 冒泡排序
func BubbleSort(arr []int) {n := len(arr)              // 获取切片长度for i := 0; i < n-1; i++ { // 外层循环控制遍历的次数for j := 0; j < n-i-1; j++ { // 内层循环控制每轮遍历的次数,每完成一轮,最大数就“冒泡”到最后if arr[j] < arr[j+1] { // 比较相邻元素,如果前一个比后一个大,则交换arr[j], arr[j+1] = arr[j+1], arr[j] // 两个元素换位置}}}
}

只需要一丁点的代码即可

在第八行代码中,我们将 ">" 改成了 "<" ,这样就变成了 从大到小排序了

循环细节

心细的同学已经发现,我们的外层循环中,有 "n - 1",而内层循环中,有 "n - i - 1"

外层循环

外层循环控制的是遍历数组的总轮数。在冒泡排序中,没完成一轮遍历,都会确保至少有一个元素被放置到它最终的位置上。因此,随着排序的进行,未排序的元素数量逐渐减少。

  • 初始时,未排序的元素是整个数组,长度为 n
  • 第一轮遍历后,最大的元素被放到了数组的最后一位,因此未排序的元素减少了一个,剩下 n - 1 个
  • 第二轮遍历后,第二大的元素被放到了倒数第二个,未排序的元素再减少一个,剩下 n - 2 个
  • 以此类推,直到所有的元素都排序完成

因此,外层循环的次数是 n - 1,即

for i := 0; i < n - 1; i ++ {}

内层循环

内层循环负责在每一轮遍历中,通过相邻元素的比较和交换,将未排序部分的最大元素"冒泡"到其正确位置。随着外层循环的进行,每一轮结束后,数组的末尾都会增加一个已排序的元素(即最大元素),因此内层循环的遍历范围需要相应减少。

  • 初始时,内层循环需要遍历整个未排序的数组,即 j 从 0 到 n - 1。但由于每次遍历结束时,最后一个元素都会是未排序部分的最大值,所以实际上内层循环只需要遍历到 n - 2 (因为最后一个元素已经是最大的了,无需再比较)
  • 随着外层循环的进行(即 i 的增加),每一轮结束时,数组的末尾都会增加一个已排序的元素,因此,每进入下一轮外层循环,内层循环的遍历范围就可以减少一个元素,即 n - i - 1

综上,内层循环的条件是

for j := 0; j < n - i - 1; j ++ {}

这里的 n - i - 1 确保了内层循环每次只遍历当前未排序的部分。

总结

外层循环的减 1 是因为每轮排序后,都有一个元素被确定位置,不需要再参与后续的排序;

内层循环的减 1 和减 i 是因为随着排序的进行,未排序的元素数量在逐渐减少,需要相应地调整遍历范围。

冒泡排序的适用场景

尽管冒泡排序在大多数情况下并不是最高效的排序算法(其平均和最坏情况时间复杂度均为 O( n ^ 2),其中 n 是数组的长度),但在某些特定场景下,它仍然有其应用价值

1. 数据量非常小

当需要排序的数据量非常小时,冒泡排序的简单性可能会使其成为一种快速且易于实现的解决方案

2. 数据几乎有序

如果数据已经是接近排序的状态,那么冒泡排序的效率会相对较高,因为它在遍历过程中可以迅速地将大部分元素排序好,从而减少后续遍历的次数

3. 教学用途

由于其算法简单易懂,冒泡排序经常被用作教学算法,帮助学生理解排序算法的基本思想和过程

4. 稳定性

冒泡排序是一种稳定的排序算法,即如果两个相等的元素在排序前的相对顺序和在排序后的相对顺序相同。在某些需要保持元素原始的场合,冒泡排序可能是一个合适的选择

综上所述,虽然冒泡排序在大多数情况下不是最优选择,但在特定场景下,它仍然有其独特的优势和价值。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 20.rabbitmq插件实现延迟队列
  • JAVA(IO流-字节流)day 7.29
  • php将数字转为中文汉字
  • 计算机毕业设计LSTM+Tensorflow股票分析预测 基金分析预测 股票爬虫 大数据毕业设计 深度学习 机器学习 数据可视化 人工智能
  • Javascript前端面试基础4【每日学习并更新10】
  • IndexError: list index out of range
  • 物联网架构之Hadoop
  • 区块链软硬件协同,做产业数字化转型的“安全官” |《超话区块链》直播预告
  • 【C++】学习笔记——C++11_1
  • 0729_驱动1 异步通知
  • RocketMQ Server Windows安装
  • 现在有什么赛道可以干到退休?
  • 【音视频之SDL2】Ubuntu编译配置SDL2环境
  • 如何实现无公网IP远程访问本地内网部署的Proxmox VE虚拟机平台
  • 莫斯科国际机场折腾“豪游”的我们
  • (三)从jvm层面了解线程的启动和停止
  • Electron入门介绍
  • Fundebug计费标准解释:事件数是如何定义的?
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Javascript 原型链
  • Koa2 之文件上传下载
  • Magento 1.x 中文订单打印乱码
  • PHP的Ev教程三(Periodic watcher)
  • php的插入排序,通过双层for循环
  • Rancher-k8s加速安装文档
  • 大数据与云计算学习:数据分析(二)
  • 记一次用 NodeJs 实现模拟登录的思路
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 消息队列系列二(IOT中消息队列的应用)
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 自定义函数
  • 自动记录MySQL慢查询快照脚本
  • Java总结 - String - 这篇请使劲喷我
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​MySQL主从复制一致性检测
  • ​zookeeper集群配置与启动
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # Redis 入门到精通(七)-- redis 删除策略
  • #《AI中文版》V3 第 1 章 概述
  • #AngularJS#$sce.trustAsResourceUrl
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • $(function(){})与(function($){....})(jQuery)的区别
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (回溯) LeetCode 131. 分割回文串
  • (强烈推荐)移动端音视频从零到上手(上)
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转) RFS+AutoItLibrary测试web对话框