go语言基本排序算法

package mainimport "fmt"func main() {BubbleSort()SelectSort()InsertSort()MergeSort()QuickSort()HeapSort()ShellSort()
}//冒泡排序
func BubbleSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}for i := 0; i < len(str)-1; i++ {flag := falsefor j := len(str) - 1; j > i; j-- {if str[j] < str[j-1] {str[j], str[j-1] = str[j-1], str[j]flag = true}}if !flag {break}}fmt.Println("BubbleSort: ", str)
}//选择排序
func SelectSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}for i := 0; i < len(str)-1; i++ {min := ifor j := i + 1; j <= len(str)-1; j++ {if str[j] < str[min] {min = j}}if min != i {str[i], str[min] = str[min], str[i]}}fmt.Println("SelectSort: ", str)
}//插入排序
func InsertSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}for i := 1; i <= len(str)-1; i++ {temp := str[i]j := i - 1for ; j >= 0 && str[j] > temp; j-- {str[j+1] = str[j]}str[j+1] = temp}fmt.Println("InsertSort: ", str)
}// 希尔排序   与插入排序比较,把原来按顺序变成了相隔增量,增量不能小于3
func ShellSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}//increment相隔数量// for increment := len(str) / 3; increment > 0; increment /= 3 {increment := len(str)for increment > 0 {increment = increment / 3//此过程类似于插入排序的过程for i := increment; i <= len(str)-1; i++ {key := str[i]j := i - increment//按照increment,数组从j到0进行交换比较for ; j >= 0 && str[j] > key; j -= increment {str[j+increment] = str[j]}//str[j+increment] = key}}fmt.Println("ShellSort: ", str)
}//堆排序
func HeapSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}for i := len(str) / 2; i >= 0; i-- {Heap_Adjust_0(str, len(str), i)}for i := len(str) - 1; i > 0; i-- {str[i], str[0] = str[0], str[i]Heap_Adjust_0(str, i, 0)}fmt.Println("HeapSort: ", str)
}// 函数0和函数1是同一种思路,只是写法不同// 堆调整函数0
func Heap_Adjust_0(str []int, length, index int) {parent := indexchild := 2*parent + 1for ; child < length-1; child *= 2 {if str[child] < str[child+1] {child++}if str[parent] < str[child] {str[parent], str[child] = str[child], str[parent]parent = child}}
}// 堆调整函数1
func Heap_Adjust_1(str []int, length, index int) {largest := index     // 初始化最大元素为根节点left := 2*index + 1  // 左子节点索引right := 2*index + 2 // 右子节点索引// 如果左子节点大于根节点if left < length && str[left] > str[largest] {largest = left}// 如果右子节点大于最大元素if right < length && str[right] > str[largest] {largest = right}// 如果最大元素不是根节点if largest != index {str[index], str[largest] = str[largest], str[index]// 递归调整受影响的子树Heap_Adjust_2(str, length, largest)}
}//归并排序
func MergeSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}str = Merging_Sort(str)fmt.Println("MergeSort: ", str)
}func Merging_Sort(str []int) []int {if len(str) <= 1 {return str}mid := len(str) / 2left := Merging_Sort(str[:mid])right := Merging_Sort(str[mid:])res := Merge_1(left, right)return res
}//合并函数0
func Merge_0(left, right []int) []int {result := make([]int, len(left)+len(right))i, j := 0, 0for k := 0; k < len(result); k++ {if i >= len(left) {result[k] = right[j]j++} else if j >= len(right) {result[k] = left[i]i++} else if left[i] < right[j] {result[k] = left[i]i++} else if right[j] < left[i] {result[k] = right[j]j++}}return result
}//合并函数1
func Merge_1(left, right []int) []int {//result := make([]int, 0, len(left)+len(right))var result []inti, j := 0, 0for {if i >= len(left) {result = append(result, right[j:]...)break} else if j >= len(right) {result = append(result, left[i:]...)break} else if left[i] < right[j] {result = append(result, left[i])i++} else if right[j] < left[i] {result = append(result, right[j])j++}}return result
}//快速排序
func QuickSort() {str := []int{9, 1, 5, 8, 3, 7, 4, 6, 2}Quicking_Sort(str, 0, len(str)-1)fmt.Println("QuickSort: ", str)
}func Quicking_Sort(str []int, low, high int) {if low < high {pivot := Partition(str, low, high)Quicking_Sort(str, low, pivot-1)Quicking_Sort(str, pivot+1, high)}
}//获取基准值函数
func Partition(str []int, low, high int) int {pivotky := str[low]for low < high {for low < high && str[low] < pivotky {low++}for low < high && str[high] > pivotky {high--}str[low], str[high] = str[high], str[low]}return low
}

排序算法的指标性能比较

                                                                        表1

排序方法平均时间复杂度最好时间复杂度最坏时间复杂度辅助空间稳定性
冒泡排序O(n2)O(n)O(n2)O(1)稳定
简单选择排序O(n2)O(n2)O(n2)O(1)稳定
直接插入排序O(n2)O(n)O(n2)O(1)稳定
希尔排序  O(nlogn)~O(n2)O(n1.3)O(n2)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定
快速排序O(nlogn)O(n)O(n2)O(logn)~O(n)不稳定

一、七种排序算法的性能指标说明:

        (1)冒泡排序:最坏的情况,即为序列处于逆序的情况,此时需要比较的次数为n(n-1)/2;最好的情况就是序列本身有序,那么需要比较的次数为n-1次,平均o(n2)

        (2)简单选择排序:无论最好最差情况,其比较次数均为n(n-1)/2,对于交换次数而言,最好的情况,交换0次,最差的情况,交换次数为n-1次,那么综合比较和交换的次数,平均时间复杂度为o(n2)

        (3)直接插入排序:最好的情况,即排序表本身是有序的,比较了n-1次,时间复杂度为o(n);最坏的情况,即待排序为逆序,此时需要比较(n+2)*(n-1)/2,且移动的次数也达到最大(n+4)*(n-1)/2;如果排序记录是随机的,那么根据概率相同的原则,平均比较和移动次数为n2/4,因此,最坏和平均时间复杂度均为o(n2)

        (4)希尔排序:希尔排序的好坏取决于增量的选取,究竟如何选取一个好的增量,目前仍然没有一种最好的办法。目前较好的情况,可以使希尔排序的时间复杂度缩减为O(n1.5)左右,最坏的情况仍然是o(n2)

        (5)堆排序:在构建堆的过程中,因为我们是完全二叉树从最下层最右边的非终端结点开始构建,将它与其孩子进行比较和若有必要的交换,对于每个非终端结点而言,其实最多进行两次比较和互换操作,因此这个构建堆的时间复杂度为o(n);在正式排序中,第i次取堆顶记录重建堆需要用o(logi)的时间,并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为o(nlogn);所以整体而言,对于堆排序,最好,最坏和平均情况,时间复杂度均为o(nlogn)

        (6)归并排序:一趟归并需要将待排序序列中所有记录扫描一遍,需要o(n)时间,而由完全二叉树深度可知,整个归并排序需要进行log2n,因此,总的时间复杂度为o(nlogn),并且zhe是归并排序最好,最坏,平均性能。此外,归并排序过程中,需要与原始记录序列同样数量的存储空间存放归并结果以及递归时深度为log2n的栈空间,因此空间复杂度为o(n+logn),也就是说归并排序是一种比较占用内存的算法。此外,归并排序需要两两比较,但不存在跳跃,因此归并排序也是一种稳定的排序算法。

        (7)快速排序,在最优的情况下,partition每次都划分的很均匀,这样不断的划分下去,时间复杂度为o(nlogn),在最坏的情况待排序为正序或者逆序,比较次数为n(n-1)/2,最终时间复杂度为o(n2),那么平均情况为o(nlogn)。就空间复杂度而言,主要是递归造成的栈空间使用,最好情况,递归深度为o(log2n),空间复杂度也就为o(n),最坏的情况需要进行n-1递归调用,空间复杂度o(n),所以平均情况空间复杂度也就为o(logn)由于关键字的比较和交换是跳跃进行的,所以快速排序不是一种稳定的算法。

二、七种算法在各个指标上的相互比较:

接下来,从各个指标分析这七种算法的优劣:

        (1)从算法的简单性来看:

                简单算法:冒泡,简单选择,直接插入

                改进算法:希尔,堆,归并,快速

        (2)从平均情况来看,显然三种改进算法要好于希尔排序,远远胜于前三种简单排序

        (3)从最好情况来看,冒泡排序和直接插入排序要更好一些,也就是说,如果待排序数组总是基本有序的,应该优先考虑冒泡和直接插入排序算法

        (4)从最坏的情况来看,堆排序和归并排序又强于快速排序和其他简单排序

        (5)从空间复杂度来看,归并排序和快速排序都有相应的空间要求,这样,如果执行算法的软件所处的环境非常在乎内存使用量多少,现在归并和快排显然不是一个很好的办法

        (6)从稳定性来看,归并排序独占鳌头,对于非常在乎排序稳定性的应用,归并排序是个好算法

        (7)从待排序记录的个数来说,待排序的个数n越小,采用简单排序方法越合适。反之,n越大,采用改进算法越合适。这样,我们在采用快速排序优化时,考虑增加一个阈值,当待排序数目小于阈值采用直接插入排序,否则选择快速排序

        (8)从表1来看,似乎简单选择排序是最差的算法,但也并不完全,比如,如果记录关键字本身信息量比较大,此时表面其占用内存空间较大,这样移动记录花费的时间就越多,下面给出三种简单排序算法此时的"移动"次数比较:

                                                                        表2

排序方法平均情况最好情况最差情况
冒泡o(n2)0o(n2)
简单选择o(n)0o(n)
直接插入o(n2)0o(n2)

        你会发现,此时简单选择排序在最差情况就变得很有优势,因为简单选择排序每次是通过与其后面的元素先一一比较,找到最小的元素,再与最小的元素进行交换,所以它的移动次数最多为n-1次。所以,对于数据量不是很大,但记录关键字的信息量较大的排序要求,显然简单选择排序是占优的。另外,记录关键字信息量的大小对四种改进算法影响不大。

        总结:从综合各项指标来说,经过优化的快速排序是性能最好的排序算法,但是不同的场合也应该考虑使用不同的算法来应对它。

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

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

相关文章

一步完成CalDAV账户同步,日历服务助力钉钉日历日程集中管理

在信息爆炸节奏飞快的今天&#xff0c;高效的管理时间已经成为我们工作和生活中的核心竞争力&#xff0c;复杂纷繁的日程安排&#xff0c;无处不在的提醒需求以及跨设备同步的困扰&#xff0c;这些问题仿佛都在呼唤着一个更智能、更便捷、更可靠的解决方案。 而华为日历App&am…

企业内部机密视频安全保护|如何防止企业内部机密视频泄露?

在企业数字化进程飞速发展的今天&#xff0c;视频内容已成为承载企业内部培训、战略会议、产品机密和核心技术的关键载体。一次意外的泄露&#xff0c;不仅可能导致知识产权流失&#xff0c;更会让企业声誉和市场竞争力遭受重创。面对无孔不入的安全威胁&#xff0c;企业该如何…

C# Deconstruct | 简化元组与对象的数据提取

官方文档&#xff1a;析构元组和其他类型 - C# | Microsoft Learn 标签&#xff1a;Deconstruct、Tuple、record、模式匹配 PS&#xff1a;record相关内容后续还会继续更新&#x1f504; 模式匹配可以查看我的另一篇&#x1f449;模式匹配 目录1. 概述2. 基本用法2.1 元组解…

R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案

摘要 在生物信息学、数据挖掘等领域的集合分析中,传统 Venn 图在多维度数据展示时存在信息拥挤、可读性差等问题。本文基于 R 语言的 ComplexUpset 包,以基因表达研究为场景,从包安装、数据准备到可视化实现,完整演示如何制作正刊级别的集合交集图,解决多条件下差异基因(…

​导游|基于SprinBoot+vue的在线预约导游系统

在线预约导游系统 基于SprinBootvue的在线预约导游系统 一、前言 二、系统设计 三、系统功能设计 前台功能实现 后台功能实现 管理员模块实现 导游模块实现 用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&am…

SQL server 异常 出现错误 824

2025-08-27 01:36:37,324 ERROR c.z.i.w.DatabaseUtils [Scheduled-7] Error executeStoredProcedure SQL script: sp_RefreshDWDByDateFive警告: 在 08 27 2025 1:36AM 出现错误 824。请记录该错误和时间&#xff0c;并与您的系统管理员联系。 2025-08-27 01:36:37,332 ERROR …

制造业生产线连贯性动作识别系统开发

制造业生产线连贯性动作识别系统开发 第一部分&#xff1a;项目概述与理论基础 1.1 项目背景与意义 在现代智能制造环境中&#xff0c;尽管自动化程度不断提高&#xff0c;但人工操作仍然在复杂装配任务中扮演着不可替代的角色。研究表明&#xff0c;人机协作被视为打破传统人机…

什么是Jmeter? Jmeter工作原理是什么?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 第一篇 什么是 JMeter&#xff1f;JMeter 工作原理 1.1 什么是 JMeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试&a…

Linux网络基础1(一)之计算机网络背景

文章目录计算机网络背景网络发展认识 "协议"高小琴例子方言例子计算机网络背景 网络发展 独立模式: 计算机之间相互独立; 网络互联: 多台计算机连接在一起, 完成数据共享; 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起; 广域网WAN: 将远隔千里的计算…

如何在数学建模赛中实现模型创新?

模型创新性在国赛数学建模中&#xff0c;完备性是论文的基本要求&#xff0c;而创新性则是决定论文能否脱颖而出的关键因素。所谓创新&#xff0c;并不仅仅指提出完全新颖的数学理论&#xff0c;而是能够在已有方法的基础上&#xff0c;通过新的问题切入点、假设修正、模型优化…

【重磅发布】flutter_chen_updater-版本升级更新

Flutter Chen Updater 一个功能强大的Flutter应用内更新插件&#xff0c;支持Android APK自动下载、安装和iOS跳转App Store。 ✨ 特性 ✅ 跨平台支持: Android APK自动更新&#xff0c;iOS跳转App Store✅ 智能下载: 支持断点续传、文件校验、多重备用方案✅ 权限管理: 自动处…

docker 1分钟 快速搭建 redis 哨兵集群

使用 docker-compose 1 分钟搭建好 1主2从3哨兵的 redis 哨兵集群 目录结构 redis-sentinel-cluster ├── check_redis.sh ├── docker-compose.yml ├── redis │ └── redis.conf ├── sentinel │ └── sentinel.confdocker-compose.yml 配置 version: 3…

Git与DevOps实战:从版本控制到自动化部署

一、版本控制1.什么是版本控制&#xff1f;版本控制用于高效追踪和管理项目开发中的代码、配置及文档变更历史&#xff0c;确保团队成员始终使用正确版本&#xff0c;并支持版本回溯、差异比较和文件恢复。它能带来以下优势&#xff1a;通过历史记录保障数据安全与完整性&#…

大模型——利用RAG构建智能问答平台实战

利用RAG构建智能问答平台实战 目前公司的智能问答平台利用RAG技术构建,现给大家分享下通RAG技术构建智能问平台的具体流程和原理。 一、什么是RAG RAG是检索增强生成技术(Retrieval-Augmented Generation),目前是构建智能问答的重要技术。RAG相比传统的检索可以可以减少…

flume事务机制详解:保障数据可靠性的核心逻辑

flume事务机制详解&#xff1a;保障数据可靠性的核心逻辑 在数据采集过程中&#xff0c;“不丢数据、不重数据” 是核心需求。Flume 之所以能在分布式环境下保证数据可靠性&#xff0c;关键在于其内置的事务机制。Flume 通过在 “Source → Channel” 和 “Channel → Sink” …

第四十九天(springboot模版注入ThymeleafFreemarkerVelocity)

开发框架-SpringBoot 参考&#xff1a;Spring Boot 中文文档 新建一个spring Boot 项目&#xff0c;修改服务器url为 aliyun.com 不然没有与jdk8版本对应的java 选择一个spring web 库&#xff0c;点击创建即可 来到这个页面点击运行 启动的是8080端口&#xff0c;用127.0.0.1…

Spring MVC 九大组件源码深度剖析(六):HandlerExceptionResolver - 异常处理的艺术

文章目录一、异常处理的核心价值二、核心接口设计三、四大内置实现类源码解析1. ExceptionHandlerExceptionResolver&#xff08;现代异常处理核心&#xff09;2. ResponseStatusExceptionResolver&#xff08;HTTP状态码处理&#xff09;3. DefaultHandlerExceptionResolver&a…

MCP(Model Context Protocol,模型上下文协议)介绍

1. 背景 随着大语言模型&#xff08;LLM, Large Language Model&#xff09;的应用越来越广泛&#xff0c;一个核心问题逐渐凸显&#xff1a; 模型在对话或推理时&#xff0c;往往只能依赖有限上下文窗口。外部工具、知识库、应用接口如何统一接入模型&#xff0c;缺乏标准协议…

synchronized的锁对象 和 wait,notify的调用者之间的关系

谁调用了wait和notify方法&#xff0c;会决定这两个方法的控制范围吗&#xff1f;你的问题非常深入&#xff0c;涉及到 wait() 和 notify() 方法的控制范围和作用域。让我们详细分析一下&#xff1a;✅ 核心概念&#xff1a;控制范围由“锁对象”决定wait() 和 notify() 的控制…

【技术教程】如何将文档编辑器集成到用 .Net 编写的网络应用程序中

在现代网络应用中&#xff0c;​富文本编辑能力已成为内容管理系统的核心需求。对于 .NET 开发者而言&#xff0c;选择适合的编辑器并高效集成&#xff0c;是构建企业级应用的关键一步&#xff0c;可让项目管理、 CRM 或定制化系统具备原生办公能力&#xff0c;消除频繁切换应用…