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

news2024/11/26 15:15:48

目录

前言

冒泡排序

代码示例

1. 算法包

2. 冒泡排序代码

3. 模拟排序

4. 运行程序

5. 从大到小排序

循环细节

外层循环

内层循环

总结

循环次数测试

假如 10 条数据进行排序

假如 20 条数据进行排序

假如 30 条数据进行排序

冒泡排序的适用场景

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 main

import (
	"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 是因为随着排序的进行,未排序的元素数量在逐渐减少,需要相应地调整遍历范围。

循环次数测试

按照上面示例进行测试:

假如 10 条数据进行排序

外层循环了 9

内层循环了 45

总计循环了 54

假如 20 条数据进行排序

外层循环了 19 

内层循环了 190 

总计循环了 209

假如 30 条数据进行排序

外层循环了 29 

内层循环了 435 

总计循环了 464 次

...

会发现,仅仅只是增加了 10 条数据,或者是 20 条数据,循环次数则是成几倍甚至十倍增长,所以数据量稍微多一点,是不建议使用 冒泡排序

冒泡排序的适用场景

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

1. 数据量非常小

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

2. 数据几乎有序

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

3. 教学用途

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

4. 稳定性

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

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

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

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

相关文章

大数据-55 Kafka sh脚本使用 与 JavaAPI使用 topics.sh producer.sh consumer.sh kafka-clients

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

WireShark看tcp网速

1、过滤对应的tcp流 2、统计->TCP流图形->窗口尺寸 3、"接收通过窗口值/时间" 可以得到tcp的接收速度

强化学习时序差分算法之Sarsa算法——以悬崖漫步环境为例

1.导入必要的库环境&#xff0c;代码如下所示。 import matplotlib.pyplot as plt import numpy as np from tqdm import tqdm 2.本悬崖漫步环境中无需提供奖励函数以及状态转移函数&#xff0c;而需提供一个与智能体进行交互的step()函数&#xff0c;该函数输入为智能体当前…

Python time模块格式化时间的N种技巧

文末赠免费精品编程资料~~ 是不是经常对着电脑屏幕上的日期时间发呆&#xff0c;心想&#xff1a;“要是能随心所欲地格式化这些数字就好了。”今天&#xff0c;我们就一起探索Python中的时间宝藏——time模块&#xff0c;让你轻松玩转时间显示&#xff0c;从新手进阶为时间格…

AI算力的新时代:智算中心的挑战与创新

随着AI的发展&#xff0c;作为AI三要素算法、数据、算力中的基础设施——算力首先迎来了高速的发展。智算中心作为AI时代承载算力的关键基础设施&#xff0c;在政策、市场的双重驱动下进入了高速建设周期&#xff0c;其在推动数字经济发展和技术进步方面发挥着重要作用&#xf…

【Gin】深度解析:在Gin框架中优化应用程序流程的责任链设计模式(下)

【Gin】深度解析&#xff1a;在Gin框架中优化应用程序流程的责任链设计模式(下) 大家好 我是寸铁&#x1f44a; 【Gin】深度解析&#xff1a;在Gin框架中优化应用程序流程的责任链设计模式(下)✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 本次文章分为上下两部分&#xf…

数学建模--微分方程

目录 常见的微分方程模型 微分方程建模的基本步骤 代码示例 常微分方程 ​编辑 ​编辑 偏微分方程 ​编辑 应用实例 结论 如何在数学建模中准确识别和选择合适的微分方程模型&#xff1f; 微分方程模型在解决实际问题中的应用案例有哪些&#xff1f; 常微分方程&a…

SpringBoot整合FFmpeg进行视频分片上传

SpringBoot整合FFmpeg进行视频分片上传------>Windows 分片上传的核心思路&#xff1a; 将文件按一定的分割规则&#xff08;静态或动态设定&#xff0c;如手动设置20M为一个分片&#xff09;&#xff0c;用slice分割成多个数据块。为每个文件生成一个唯一标识Key&#xf…

ONNX模型的量化

我们都希望从代码中榨取更多的性能&#xff0c;对吧&#xff1f; 在现代&#xff0c;充斥着需要大量计算资源的复杂机器学习算法&#xff0c;因此&#xff0c;榨取每一点性能至关重要。 传统上&#xff0c;机器学习算法是在具有支持大量并行计算能力的 GPU 上进行训练的。但是…

WordPress建站:如何使用ChemiCloud搭建外贸独立站

以前自行搭建一个网站&#xff0c;不懂一点技术那是很难完成的&#xff0c;现如今WordPress的出现极大地降低了搭建网站的技术门槛&#xff0c;不需要懂任何代码&#xff0c;只需按步骤操作就行。WordPress 是一个非常流行的开源内容管理系统&#xff08;CMS&#xff09;&#…

职业教育计算机网络综合实验实训室建设应用案例

近年来&#xff0c;职业教育在培养技能型人才方面发挥着越来越重要的作用。然而&#xff0c;传统的计算机网络技术教学模式往往重理论、轻实践&#xff0c;导致学生缺乏实际操作能力和职业竞争力。为了改变这一现状&#xff0c;唯众结合职业教育特点&#xff0c;提出了“教、学…

Kubeflow v1.7.0 创建新用户

文章目录 为新用户创建配置文件配置用户密码重启auth生效 为新用户创建配置文件 apiVersion: kubeflow.org/v1beta1 kind: Profile metadata:name: kubeflow-cyw-example-com # replace with the name of profile you want, this will be users namespace name spec:owner:k…

STC单片机UART映射printf

文章目录 使用STC-ISP生成UART初始化函数 增加如下函数&#xff0c;注意使用printf函数需要添加 #include <stdio.h> 头文件 #include <stdio.h>void Uart1_Init(void) //9600bps12.000MHz {SCON 0x50; //8位数据,可变波特率AUXR | 0x01; //串口1选择定时器2为…

【Spring】——Spring概述、IOC、IOC创建对象的方式、Spring配置、依赖注入(DI)以及自动装配知识

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

LeetCode 101.对称二叉树 C写法

LeetCode 101.对称二叉树 C写法 思路&#xff1a; 将该树一分为二&#xff0c;左子树的左边与右子树的右边比&#xff0c;左子树的右边与右子树的左边比&#xff0c;不相等或者一边为空则不是对称。 代码&#x1f50e;&#xff1a; bool _isSymmetric(struct TreeNode* Leftroo…

程序员开发指南

在这个快节奏的时代&#xff0c;作为一名程序员&#xff0c;大家都希望能更快地开发出高质量的应用&#xff0c;而不是花费大量时间在基础设施和后台服务的搭建上。今天&#xff0c;我要向大家介绍一款专为懒人开发者准备的一站式开发应用的神器——MemFire Cloud。 一站式开发…

使用代理访问内网:实验二

目录 环境搭建 内网搭建&#xff08;win2019&#xff09; 跳板机搭建&#xff08;win10&#xff09; 实验步骤 1. win10上线kali 2. 借助msf做代理 3. 在攻击机上做个代理&#xff0c;访问目标网站 4. 使用SocksCap64工具&#xff0c;进行sock4a隧道的连接 5. 启用soc…

TypeScript 的主要特点和重要作用

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

最短路(dijkstra迪杰斯特拉)

最短路径问题在图论中是一个经典的问题&#xff0c;目的是找到从一个起始顶点到其他所有顶点的最短路径。Dijkstra算法是解决非负权图最短路径问题的常用算法。下面是一个使用Dijkstra算法解决最短路径问题的Java程序例子。 动画描述(从0节点开始更新) 问题描述 假设有一个图…

【机器学习西瓜书学习笔记——模型评估与选择】

机器学习西瓜书学习笔记【第二章】 第二章 模型评估与选择2.1训练误差和测试误差错误率误差 欠拟合和过拟合2.2评估方法留出法交叉验证法自助法 2.3性能度量查准率、查全率与F1查准率查全率F1 P-R曲线ROC与AUCROCAUC 代价敏感错误率与代价曲线代价曲线 2.4比较检验假设检验&…