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

排序算法:选择排序,golang实现

目录

前言

选择排序

代码示例

1. 算法包

2. 选择排序代码

3. 模拟排序

4. 运行程序

5. 从大到小排序

循环细节

外层循环

内层循环

总结

选择排序的适用场景

1. 数据规模非常小

2. 稳定性不重要

3. 几乎全部数据已排序

4. 教育目的


前言

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

选择排序

选择排序(Selection Sort) 是一种简单直观的排序算法,它的工作原理是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

代码示例

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

1. 算法包

创建一个 pkg/algorithm.go

mkdir pkg/algorithm.go

(如果看过上节课的冒泡排序,则已存在该文件,我们就不需要再创建了)

2. 选择排序代码

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

从小到大 排序

package pkg// BubbleSort 冒泡排序
...// SelectionSort 选择排序
func SelectionSort(arr []int) {n := len(arr) // 获取切片长度for i := 0; i < n-1; i++ {// 假设当前位置是最小的minIndex := i// 遍历未排序的部分,寻找真正的最小值的索引for j := i + 1; j < n; j++ {if arr[j] < arr[minIndex] {minIndex = j}}// 如果找到更小的数,就交换arr[i], arr[minIndex] = arr[minIndex], arr[i]}
}

3. 模拟排序

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

package mainimport ("demo/pkg""fmt"
)func main() {// 定义一个切片,这里我们模拟 10 个元素arr := []int{789, 59, 1500, 847, 633, 2456, 901, 2, 752, 100}fmt.Println("Original data:", arr) // 先打印原始数据pkg.SelectionSort(arr)             // 调用选择排序fmt.Println("New data:  ", arr)    // 后打印排序后的数据
}

4. 运行程序

打开终端,我们运行 go :

go run main.go

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

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

5. 从大到小排序

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

修改 pkg/algorithm.go 文件:

package pkg// BubbleSort 冒泡排序
...// SelectionSort 选择排序
func SelectionSort(arr []int) {n := len(arr) // 获取切片长度for i := 0; i < n-1; i++ {// 假设当前位置是最小的minIndex := i// 遍历未排序的部分,寻找真正的最小值的索引for j := i + 1; j < n; j++ {if arr[j] > arr[minIndex] {minIndex = j}}// 如果找到更小的数,就交换arr[i], arr[minIndex] = arr[minIndex], arr[i]}
}

只需要一丁点的代码即可

package pkg 算第一行,上面示例中在第十四行代码中,我们将 "<" 改成了 ">" ,这样就变成了 从大到小排序了

补充:

代码里还有一处可以完善,在最后两个数进行交换时

思考一下这一行代码:

arr[i], arr[minIndex] = arr[minIndex], arr[i]

如果,arr[minIndex] 和 arr[i] 这两个数是相同的,那么还有必要进行交换吗?

当然是可以不用交换,所以我们可以再加上一个判断:

// 如果它们不相等
if arr[minIndex] != arr[i] {// 如果找到更小的数,就交换arr[i], arr[minIndex] = arr[minIndex], arr[i]
}

循环细节

在选择排序算法中,外层循环和内层循环扮演着至关重要的角色,它们共同协作以实现对整个数组的排序。下面是这两个循环的详细说明

外层循环

  • 目的:外层循环负责控制排序的轮次。对于包含 n 个元素的数组,外层循环需要进行 n - 1 轮排序(因为当只剩下一个元素时,它自然就是排序好的)。每一轮排序都会从未排序的部分找到一个最小(或最大)的元素,并将其放到已排序部分的末尾
  • 起始与结束:外层循环通常从一个起始索引(如 0)开始,直到达到数组长度减 1 (n - 1) 的索引结束。这是因为当外层循环到达 n - 1 时,所有元素都已经排好序,只剩下最后一个元素(即索引为 n - 1 的元素),它自然就是已排序的
  • 作用:在每一轮排序开始时,外层循环的索引(假设为 i )代表当前已排序部分的末尾。然后,内层循环会从未排序的部分(即索引 i + 1 到 n - 1 的部分)中找到一个最小(或最大)元素的索引,并与索引 i 处的元素进行可能的交换

内层循环

  • 目的:内层循环负责在每一轮排序中,从未排序的部分找到最小(或最大)元素的索引。一旦找到,就可能与当前轮次的外层循环索引处的元素进行交换(如果它们不是同一个元素的话)
  • 起始与结束:内层循环的起始索引通常是外层循环索引的下一个位置(即 i + 1),而结束索引是数组的最后一个元素(即 n - 1)。这是因为内层循环需要遍历整个未排序的部分来找到最小(或最大)的元素
  • 作用:在每一轮外层循环中,内层循环都会遍历未排序的部分,通常比较来找到最小(或最大)元素的索引。这个索引会被存储在某个变量中(如 minIndex),以便在遍历结束后与外层循环索引处的元素进行可能的交换
  • 交换:如果内层循环找到了一个比外层循环索引处更小的元素(即 minIndex 不等于外层循环的索引 i ),那么就需要进行交换操作,将这两个元素的位置互换。这样,外层循环索引处的元素就变成了当前轮次中未排序部分的最小(或最大)元素,被正确地放置在了已排序部分的末尾

总结

外层循环控制排序的轮次,每一轮都试图从未排序的部分找到一个最小(或最大)元素,并将其放置到正确的位置上。内层循环则负责在每一轮中执行这个查找和可能的交换操作。通过这两层循环的协作,整个数组最终被排序完成。

选择排序的适用场景

尽管选择排序在大多数现代应用中不是最高效的排序算法(其平均和最坏情况时间复杂度都是 O(n ^ 2)),但在某些特定场景下,它仍然有其用途

1. 数据规模非常小

对于非常小的数据集,选择排序在效率损失可能微不足道,而它实现简单,易于理解和实现

2. 稳定性不重要

选择排序不是稳定的排序算法(即相等元素的相对顺序可能会改变)。如果应用场景不需要保持元素的原始相对顺序,那么选择排序可以作为一个简单的选择

3. 几乎全部数据已排序

虽然理论上来说,即使数据几乎全部已排序,选择排序的效率也不会显著提升,但在某些特定应用中,如果已知数据集接近排序状态,并且算法设计可以利用这一点(例如,通过提前终止不必要的比较)。则可能略有优势。然而,这通常需要结合其他优化技巧

4. 教育目的

由于选择排序简单直观,它常被用于教学目的,帮助学生理解排序算法的基本概念和工作原理

总之,尽管存在更高效的排序算法,但在特定场景下,选择排序仍然有其用武之地。

相关文章:

排序算法:选择排序,golang实现

目录 前言 选择排序 代码示例 1. 算法包 2. 选择排序代码 3. 模拟排序 4. 运行程序 5. 从大到小排序 循环细节 外层循环 内层循环 总结 选择排序的适用场景 1. 数据规模非常小 2. 稳定性不重要 3. 几乎全部数据已排序 4. 教育目的 前言 在实际场景中&#xf…...

【测试】博客系统的测试报告

项目背景 个人博客系统采用了 SSM 框架与 Redis 缓存技术的组合 &#xff0c;为用户提供了一个功能丰富、性能优越的博客平台。 在技术架构上 &#xff0c;SSM 框架确保了系统的稳定性和可扩展性。Spring 负责管理项目的各种组件 &#xff0c;Spring MVC 实现了清晰的请求处理…...

PointCLIP: Point Cloud Understanding by CLIP

Abstract 近年来&#xff0c;基于对比视觉语言预训练(CLIP)的零镜头和少镜头学习在二维视觉识别中表现出了令人鼓舞的效果&#xff0c;该方法在开放词汇设置下学习图像与相应文本的匹配。然而&#xff0c;通过大规模二维图像-文本对预训练的CLIP是否可以推广到三维识别&#x…...

搜索(剪枝)

定义&#xff1a; 剪枝&#xff0c;就是减少搜索树的规模、尽早排除搜索树中不必要分支的一种手段。 在深度优先搜索中&#xff0c;有以下几类常见的剪枝方法: 优化搜索顺序排除等效冗余可行性剪枝最优性剪枝记忆化剪枝 例题1&#xff1a;AcWing 167.木棒 题目&#xff1a;…...

python基础知识点

最近系统温习了一遍python基础语法&#xff0c;把自己不熟知的知识点罗列一遍&#xff0c;便于查阅~~ python教程 Python 基础教程 | 菜鸟教程 1、python标识符 以单下划线开头 _foo 的代表不能直接访问的类属性&#xff0c;需通过类提供的接口进行访问&#xff0c;不能用 f…...

Android SurfaceFlinger——GraphicBuffer获取内存信息(三十一)

上一篇文章介绍了 GraphicBuffer 初始化的 initWithSize() 函数中的申请内存流程,这里我们看一下另一个比较重要的函数,GraphicBufferMapper. getTransportSize 获取内存信息。该函数通常在需要了解缓冲区的实际内存占用情况时调用,例如在调试内存使用情况或优化性能时。 一…...

基于 SASL/SCRAM 让 Kafka 实现动态授权认证

一、说明 在大数据处理和分析中 Apache Kafka 已经成为了一个核心组件。然而在生产环境中部署 Kafka 时&#xff0c;安全性是一个必须要考虑的重要因素。SASL&#xff08;简单认证与安全层&#xff09;和 SCRAM&#xff08;基于密码的认证机制的盐化挑战响应认证机制&#xff…...

通用多级缓件组件

背景 业界第三方缓存框架一般为redis&#xff0c;本地缓地ehcache或guava&#xff0c;一般通过spring提供的restTemplate操作缓存 然而这样会存在以下问题&#xff1a; 与缓存中间件强耦合需手动整合多级缓存不支持注解数据更新时无法自动刷新缓存存在缓存穿透、缓存击穿、缓…...

MindIE Service服务化集成部署通义千问Qwen模型

一、昇腾开发者平台申请镜像 登录Ascend官网昇腾社区-官网丨昇腾万里 让智能无所不及 二、登录并下载mindie镜像 #登录docker login -u XXX#密码XXX#下载镜像docker pull XXX 三、下载Qwen的镜像 使用wget命令下载Qwen1.5-0.5B-Chat镜像&#xff0c;放在/mnt/Qwen/Qwen1.5-…...

chrome 接口请求等待时间(installed 已停止)过长问题定位

参考: 解决实际项目中stalled时间过久的问题 背景: 测试反馈系统开 6 个标签页后, 反应变的很慢 定位: 看接口请求瀑布流, 已停止时间很长, 后端返回速度很快, 确定是前端的问题 推测是并发请求窗口数量的问题, 屏蔽部分一直 pending 的接口, 发现速度正常了, 搜到上面的参…...

HDialog特殊动画效果

基于HDialog的特殊动画效果实现 业务场景 在开发过程中直接使用HDialog所展现的效果很快&#xff0c;同时不能够与用户所点击位置进行交互&#xff0c;会造成用户的体验观感不够好。因此需要实现一种能够从用户点击按钮位置以可变动画效果所展现的Dialog效果。 工作原理及实…...

基因组挖掘指导天然药物分子的发现-文献精读34

基因组挖掘指导天然药物分子的发现 摘要 天然产物是临床药物的主要来源&#xff0c;也是新药研发过程中先导化合物结构设计和优化的灵感源泉。但传统策略天然药源分子的发现却遭遇了瓶颈&#xff0c;新颖天然产物的数量逐渐无法满足现代药物开发的需求和应对全球多药耐药的威胁…...

hcip学习 DHCP中继

DHCP 中继 在可能收到 DHCP Discover 报文的接口配置 DHCP 中继&#xff0c; 指明 DHCP 服务器的地址&#xff0c;然后将 DHCP 发现报文以单播的形式送到 DHCP 服务器上 DHCP 中继报文的源地址和目标地址怎么确定 1、源地址&#xff1a;收到 Discover 报文的接口地址 2、目…...

[Mysql-函数、索引]

目录 函数&#xff1a; 日期函数 字符串函数 数学函数 聚合函数 索引&#xff1a; 索引分类 慢查询 创建索引 函数&#xff1a; MySQL函数&#xff0c;是一种控制流程函数&#xff0c;属于数据库用语言。 MySQL常见的函数有&#xff1a; 数学函数 用作常规的数学运…...

org.eclipse.jgit 简单总结

org.eclipse.jgit 是一个用于处理 Git 版本控制系统的纯 Java 库。它允许你读取和写入 Git 仓库&#xff0c;执行如克隆、拉取、推送、提交等操作。下面我将通过几个例子来展示如何使用 org.eclipse.jgit 进行一些常见的 Git 操作。 1. 克隆仓库 克隆一个远程 Git 仓库到本地目…...

Fork软件笔记:一键拉取仓库所有模块

Fork是一个好用的git工具&#xff0c;只是没有中文而已&#xff08;不过不用翻译也能看使用&#xff09;。 工具下载地址&#xff1a;https://fork.dev/ 界面展示&#xff1a; 当项目中仓库模块比较多时&#xff0c;可以看到每个模块都是一个分页&#xff0c;每一个都要手动切换…...

常见的锂电保护芯片 单节锂电保护/双节锂电保护芯片

目前外出贸易的要求不断增多&#xff0c;出口的产品基本上都需要带上锂电保护芯片 以下是常见的单节锂电保护芯片的选型 包括了市面上大部分的可用型号。 锂电保护芯片的脚位上面基本都是通用&#xff0c;可以直接替代 双节的锂电保护使用情况较少&#xff0c;需要外置MOS管调节…...

初识Java(六)

一、String类 1、类中有操作字符串的方法 查找&#xff1a;找到某个字符是字符串内的第几个&#xff1a;charAt&#xff1b;找到某个字符在字符串内第一次出现的下标&#xff1a;index 替换&#xff1a;替换所有&#xff1a;replaceAll&#xff1b;替换首个&#xff1a;repla…...

Spring-原理篇-DispatcherServlet 初始化 怎么和IOC进行了打通?

委托模式的体现&#xff0c;在初始化醒目的时候Spring MVC为我们提供了一个DispatcherServlet&#xff0c;映射了所有的路径&#xff0c;所有的请求都会先到达这里然后被转发到具体的Controller 进行处理&#xff0c;此文来探索一下&#xff0c;DispatcherServlet 初始化的时候…...

关于swift- OC混编使用Pod遇到的2个错误

错误1 Cannot find interface declaration for UITableViewCell, superclass of "DEFUITalbleViewCell" Cannot find interface declaration for UIView, superclass of "DefUIView" Cannot find interface declaration for 系统类, superclass of "自…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...