排序算法2

排序算法1-CSDN博客

排序算法1提及较为基础(暴力实现,复杂度较高)排序算法不适合数据量较大场景比如序列长度达到1e5

接下来蓝桥另一道题目理解其它排序算法

蓝桥3226

蓝桥账户中心

样例

5

1 5 9 3 7

4、快速排序

        快速排序是一种高效的排序算法,采用分治法(Divide and Conquer)(二分思想)策略来对一个序列进行排序。

      快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

算法步骤

1. 从数列中挑出一个元素,称为 “基准”(pivot),一般选择乱序数组的第一个元素;

2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。

3.在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。值得注意的是,从每次‘分区’的过程中看,除了筛选相较于‘基准值’小或者大的数以外,不做额外的排序

 4.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。

递归的性质看,递归的结构特点是基于栈的,计算顺序满足‘后进先出’,也就是输入乱序数组后,会每一轮选出一个基准值,然后筛选相较于‘基准值’小或者大的数放入左边序列放入右边序列之后递归处理这两个序列基准值不再进入排序过程因为本轮结束基准值位置正确的后面就是一直递归两边排序数组长度都为1每一轮一个基准值选出排序序列迭代完成排序

# li[left,right]按照小于等于(等于基准值的元素放在左边或者右边都可以)基准值、基准值、大于等于基准值
# 定义一个函数返回每一轮筛选的基准值下标
def num_partition(li,left,right):# left为每一轮基准值的初始化下标# 放置 小于等于 基准值元素的下标idx = left+1# 除选出的序列第一个元素作为基准值,遍历当前序列剩下的元素for i in range(left+1,right+1):if li[i] <= li[left]:# 放左边li[idx],li[i] = li[i],li[idx]# 本轮基准值下标后移1idx += 1# 小于等于本轮基准值的元素为li[left+1,idx-1],上述设定小于等于都放左边li[left],li[idx-1] = li[idx-1],li[left]return idx-1# 基于定义好的返回每轮基准值下标的函数,实现快速排序
def quick_sort(li,left,right):# print(li)# left == right时排序完成if left < right:# 选本轮基准值mid = num_partition(li,left,right)# 基于 二分 的思想# 递归左边quick_sort(li,left,mid-1)# 递归右边quick_sort(li,mid+1,right)n = int(input())
li = list(map(int,input().split()))
quick_sort(li,0,n-1) # n-1:len(li)-1
print(' '.join(map(str,li)))

5、归并排序

        归并排序(Merge Sort)是一种基于分治法的比较排序算法,其基本思想是将数组分成两个子数组,分别对这两个子数组进行排序,然后将它们合并成一个有序数组。归并排序在时间复杂度和稳定性方面表现优异。归并排序的实现由两种方法

  • 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第 2 种方法);
  • 自下而上的递归;

和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn) 的时间复杂度。代价是需要额外的内存空间

算法步骤

1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

2.设定两个指针,最初位置分别为两个已经排序序列的起始位置;

3.比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

4.重复步骤 3 直到某一指针达到序列尾;

5.将另一序列剩下的所有元素直接复制到合并序列尾。

输出结果来看归并排序因为递归排序所以后往前

从树状结构来理解这个递归过程:

# 定义函数:用于合并两个序列。后续merge_sort函数递归调用 把序列一路递归到长度为1的两个来跑merge
def merge(li1,li2):result = []while len(li1)!=0 and len(li2)!=0:if li1[0]<=li2[0]:result.append(li1.pop(0))else:result.append(li2.pop(0))result.extend(li1)result.extend(li2)return resultdef merge_sort(li):# 一路递归到序列剩下一个元素print(li)if len(li)<2:return li# 基于二分的思想mid = len(li)//2left = merge_sort(li[:mid])right = merge_sort(li[mid:])return merge(left,right)n = int(input())
li = list(map(int,input().split()))
print(' '.join(map(str,merge_sort(li))))

6、计数排序

        计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

计数排序与桶排序的区别

1. 基本概念

        计数排序:计数排序是一种线性时间复杂度的排序算法,适用于已知范围的整数排序。它通过一个额外的数组来记录每个元素的出现次数,然后根据这些计数重新构建排序后的数组。

        桶排序:桶排序是一种分布排序算法,它将元素分布到有限数量的桶中,每个桶再分别排序。所有桶中的元素收集起来以后就是有序的。

2. 适用条件

计数排序:

        适用于整数排序。

        需要知道输入数据的最小值和最大值。空间复杂度较高,因为需要一个额外的计数数组。时间复杂度为 O(n+k),其中 n 是数据的数量,k 是数据的范围。

桶排序:

        适用于任意类型的数据(只要可以比较大小)。

        不需要知道输入数据的最小值和最大值。空间复杂度取决于桶的数量和数据分布。时间复杂度为 O(n+k),其中 n 是数据的数量,k 是桶的数量。

3. 实现步骤

计数排序:

        找到输入数据中的最小值和最大值。

        创建一个计数数组并初始化为零。遍历输入数据,统计每个值的出现次数。根据计数数组重建排序后的数据。

桶排序:

        创建若干个空桶。

        将输入数据分配到各个桶中。对每个桶进行单独排序。依次从各个桶中取出数据,得到有序的结果。

值得注意的是,如果不通过一些内存的优化策略,使用计数排序会报内存错误

内存错误(MemoryError) 是因为计数排序需要为数据范围(maxvalue - minvalue + 1)分配一个大小为 O(k) 的数组。当数据的范围(即 maxvalue - minvalue)非常大时,分配的计数数组可能需要超出可用内存。

原因分析
1.数据范围过大: 计数排序创建的 count 数组,其长度为 maxvalue - minvalue + 1,与数据的范围成正比。如果 maxvalue 和 minvalue 之间的差距非常大(比如几百万甚至更大),那么需要创建一个超大数组,导致内存溢出。
2.不是所有数据都连续: 计数排序默认假设数据是连续的。如果输入数据是稀疏的(如 1 和 1000000 之间只有少量值),这种实现方式会浪费大量内存。

示例:
假设输入数据 m = [1, 1000000],那么计数数组的大小会是 1000000 - 1 + 1 = 1000000。即使实际数据量只有 2 个数,仍然会为 100 万个位置分配内存

一个可行的策略是哈希表代替计数数组,改用一个字典(哈希表)来记录元素的出现次数,这样可以避免为稀疏数据分配多余的空间。

def counting_sort_optimized(m):# 统计每个元素的出现次数count = {}for num in m:if num in count:count[num] += 1else:count[num] = 1# 根据统计结果生成排序后的数组sorted_m = []for key in sorted(count):  # 按键值升序排序sorted_m.extend([key] * count[key])return sorted_mn = int(input())
m = list(map(int, input().split()))
a = counting_sort_optimized(m)
print(' '.join(map(str, a)))

7、桶排序

        桶排序(Bucket Sort)是一种基于分布的排序算法,也称为箱排序。它通过将数据分到若干个有序的“桶”中,然后对每个桶进行单独排序,最后将所有桶中的数据合并起来得到最终的排序结果。桶排序适用于数据分布均匀且数据量较大的情况,其时间复杂度为 O(n+k),其中 n 是待排序元素的数量,k 是桶的数量。

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:

1.在额外空间充足的情况下,尽量增大桶的数量

2.使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中。

3.同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

什么时候最快

当输入的数据可以均匀的分配到每一个桶中。

什么时候最慢

当输入的数据被分配到了同一个桶中。

例子演示:序列[11,22,33,44,45,56,77,88,99]

def bucket_sort(m,bucket_count):# m:序列;bucket_count:多少个桶minvalue,maxvalue = min(m),max(m)# 桶的大小bucket_size = (maxvalue - minvalue+1)// bucket_count+1# 存放每个桶 []代表一个桶res = [[] for _ in range(bucket_count+1)]for i in m: # m个桶idx = (i - minvalue)//bucket_sizeres[idx].append(i)# ans存放排序结果ans = []for res_i in res:res_i.sort()ans += res_ireturn ansn = int(input())
m = list(map(int,input().split()))
a = bucket_sort(m,min(n,10000))
print(' '.join(map(str,a)))

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

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

相关文章

go结构体匿名“继承“方法冲突时继承优先顺序

在 Go 语言中&#xff0c;匿名字段&#xff08;也称为嵌入字段&#xff09;可以用来实现继承的效果。当你在一个结构体中匿名嵌入另一个结构体时&#xff0c;嵌入结构体的方法会被提升到外部结构体中。这意味着你可以直接通过外部结构体调用嵌入结构体的方法。 如果多个嵌入结…

Ubuntu Server 22.04.5 从零到一:详尽安装部署指南

文章目录 Ubuntu Server 22.04.5 从零到一&#xff1a;详尽安装部署指南一、部署环境二、安装系统2.1 安装2.1.1 选择安装方式2.1.2 选择语言2.1.3 选择不更新2.1.4 选择键盘标准2.1.5 选择安装版本2.1.6 设置网卡2.1.7 配置代理2.1.8 设置镜像源2.1.9 选择装系统的硬盘2.1.10 …

鸿蒙征文|鸿蒙技术分享:使用到的开发框架和技术概览

目录 每日一句正能量前言正文1. 开发环境搭建关键技术&#xff1a;2. 用户界面开发关键技术&#xff1a;3. 应用逻辑开发关键技术&#xff1a;4. 应用测试关键技术&#xff1a;5. 应用签名和打包关键技术&#xff1a;6. 上架流程关键技术&#xff1a;7. 后续维护和更新关键技术…

C++初阶—C++入门

第一章&#xff1a;C关键字(C98) C 总计 63个关键字&#xff0c;下面只是看一下 C 有多少关键字&#xff0c;不对关键字进行具体的讲解。 第二章&#xff1a;命名空间 #include <stdio.h> #include <stdlib.h>int rand 0;int main() {printf("%d\n", r…

马斯克的 AI 游戏工作室:人工智能与游戏产业的融合新纪元

近日&#xff0c;马斯克在 X 平台&#xff08;前身为 Twitter&#xff09;发文称&#xff0c;“太多游戏工作室被大型企业所拥有&#xff0c;xAI 将启动一个 AI 游戏工作室&#xff0c;让游戏再次变得精彩”。这一言论不仅展示了马斯克对游戏行业现状的不满&#xff0c;也揭示了…

数据库期末复习题库

1. Mysql日志功能有哪些? 记录日常操作和错误信息&#xff0c;以便了解Mysql数据库的运行情况&#xff0c;日常操作&#xff0c;错误信息和进行相关的优化。 2. 数据库有哪些备份方法 完全备份&#xff1a;全部都备份一遍表备份&#xff1a;只提取数据库中的数据&#xff0…

opencv 区域提取三种算法

opencv 区域提取三种算法 1.轮廓查找 findContours()函数&#xff0c;得到轮廓的点集集合 cv::vector<cv::vector<Point>> contours;threshold(roiMat,binImg,m_pPara.m_nMinGray,m_pPara.m_nMaxGray,THRESH_BINARY);//膨胀处理Mat dilaElement getStructuringE…

如何快速上手UPR ---查看资源检测报告

上一章说了如何快速使用资源检测器 那么如何修复我们 的不规范资源呢&#xff1f; 我们都知道一些常规的美术资源优化&#xff0c;但是还是会有一些没有注意到的点 导致我们游戏的性能降低 可以看到我们的Animation 的的不规范 检查动画曲线精度 &#xff0c;其实我觉得他是…

摄影相关常用名词

本文介绍与摄影相关的常用名词。 曝光 Exposure 感光元件接收光线的过程&#xff0c;决定图像的明暗程度和细节表现。 光圈 Aperture 控制镜头进光量的孔径大小&#xff0c;用 F 值&#xff08;f-stop&#xff09; 表示。 光圈越大&#xff08;F 值越小&#xff09;&#xff0c…

NeuIPS 2024 | YOCO的高效解码器-解码器架构

该研究提出了一种新的大模型架构&#xff0c;名为YOCO&#xff08;You Only Cache Once&#xff09;&#xff0c;其目的是解决长序列语言模型推理中的内存瓶颈。YOCO通过解码器-解码器结构的创新设计&#xff0c;显著减少推理时的显存占用并提升了长序列的处理效率。 现有大模…

webrtc视频会议学习(三)

文章目录 关联&#xff1a;源码搭建coturn服务器nginx配置ice配置需服务器要开放的端口 效果 关联&#xff1a; webrtcP2P音视频通话&#xff08;一&#xff09; webrtcP2P音视频通话&#xff08;二&#xff09; webrtc视频会议学习&#xff08;三&#xff09; 源码 WebRTC…

C++ 红黑树 【内含代码】

1. 红黑树 1.1 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个节点上增加一个存储为表示节点的颜色&#xff0c;可以使Red或Black。通过对任何一条从根到叶子的路径上各个节点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出两倍&…

黑马程序员Java笔记整理(day05)

1.面向对象编程 2.用法 3.对象是什么 4.对象在计算机中是啥 5.无参与有参构造器 小结: 6.this的作用 7.小结 8.封装 9.小结 10.实体类 11.小结 12.static 13.小结 14.static修饰方法 15.static应用前景 16.几个注意事项 17.java中可以直接用类的名字创建数组&#xff0c;如: M…

Flink在Linux系统上的安装与入门

一、Flink的引入 这几年大数据的飞速发展&#xff0c;出现了很多热门的开源社区&#xff0c;其中著名的有Hadoop、Storm&#xff0c;以及后来的Spark&#xff0c;他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河&#xff0c;也以内存为赌注&#xff0c;赢得了内存计…

服务器命令行复制文件

服务器拷贝大文件太慢&#xff0c;而且容易断线&#xff0c;可以采用命令行复制文件 复制windows server服务器文件到linux服务器 scp D:\bim\uploadPath.zip ruoyixx.xx.xx.xx:/home/ruoyi/temp/uploadPath.zip 复制linux服务器文件到windows server服务器 scp ruoyixx.xx.…

(超详细图文详情)Navicat 配置连接 Oracle

1、下载依赖文件 Oracle官网下载直链&#xff1a;https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html 夸克网盘下载&#xff08;oracle19c版本&#xff09;&#xff1a;https://pan.quark.cn/s/5061e690debc 官网下载选择对应 Oracle 版…

内网不出网上线cs

一:本地正向代理目标 如下&#xff0c;本地(10.211.55.2)挂好了基于 reGeorg 的 http 正向代理。代理为: Socks5 10.211.55.2 1080python2 reGeorgSocksProxy.py -l 0.0.0.0 -p 1080 -u http://10.211.55.3:8080/shiro/tunnel.jsp 二&#xff1a;虚拟机配置proxifer 我们是…

[2024年3月10日]第15届蓝桥杯青少组stema选拔赛C++中高级(第二子卷、编程题(2))

方法一&#xff08;string&#xff09;&#xff1a; #include <iostream> #include <string> using namespace std;// 检查是否为回文数 bool isPalindrome(int n) {string str to_string(n);int left 0, right str.size() - 1;while (left < right) {if (s…

Spring MVC练习(前后端分离开发实例)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词:二十五弦弹夜月&#xff0c;不胜清怨却飞来&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4…

【ArcGIS Pro实操第11期】经纬度数据转化成平面坐标数据

经纬度数据转化成平面坐标数据 数据准备ArcGIS操作步骤-投影转换为 Sinusoidal1 投影2 计算几何Python 示例 另&#xff1a;Sinusoidal (World) 和 Sinusoidal (Sphere) 的主要区别参考 数据准备 数据投影&#xff1a; 目标投影&#xff1a;与MODIS数据相同&#xff08;Sinu…