初阶数据结构学习记录——열넷 排序(3)

news2024/9/22 10:08:05

归并排序

归并的思路其实和二叉树,快排都有点像。归并希望左、右半区间有序。和快排不同,先分裂后排序,一半一半分,分到最后每个区间只剩一个1个数字,这个区间一定是有序的,因为只有一个数字,往回走,两个数排序一下,继续往回走,逐渐排序好后,回到初始的数组,这时候整个数组就已经有序了。这里我们用另一个数组来临时存储分出来的区间去排序,排好后再拷贝回去

要开辟一块新空间的话我们需要在另一个函数里开辟,如果在一个函数里会重复开辟。

 由于是先分裂,所以先递归出区间。用四个变量记录下来两个区间两端,进入while,这两个区间从头开始一个个比较,小的就放进tmp里,这样就有序了,当然这里会出现哪个区间先结束的情况,所以后面两个while就把没出完数据的那个区间都拿出来,然后拷贝到a里,这里用a + begin是因为不可能每次都从a的首元素处拷贝,所以加上begin,拷贝每个排好的区间。

可画递归展开图来理解代码。

归并的时间复杂度不难算,整个递归像一个二叉树,高度也就是logN。每一层的归并操作可以看出就是N,所以归并是个很正规的O(N * logN)。而空间复杂度也是经典的O(N)。因为额外开了tmp这个N个数据的空间。

而上一篇的快排虽然没有额外开辟空间,但它也是递归,递归层数也是logN。每一层快排没有额外的操作,是O(1),所以它的空间复杂度是O(logN).

归并的空间复杂度刚才算了tmp,不过递归层数也要计入,所以应该是N + logN,但N很大时,logN很小啊,可以忽略不计。所以还是O(N)

非递归归并

归并的非递归需要用到链表,不过我们这里可以不用这样。和快排不一样,归并并不一定要按照递归做非递归。归并的分区间是确定,对半分,分到每个区间一个数。所以我们重点在于控制单个区间的大小。定义一个range变量控制区间,这里其实和斐波那契数列改非递归思路一样,斐波那契数列非递归就是先写出头两个数字,然后在循环里加,得到下一个数字,然后头两个数字也往后移一下。归并的非递归则是先把数组里所有的数分成若干个两个数的单位,两个数之间排序,然后让range * 2,四个数之间再排序,然后再次 * 2,变成8个数之间排序等等。虽然这个思路很不错,但是实际写代码时细节问题却有很多。这个方法也需要一个tmp。

 进入for循环后我们还是和之前一样的归并,所以直接复制过来,改改变量,而memcpy可以在整个循环结束后再拷贝,也可以一次次地拷贝,只不过在内部拷贝会更容易控制些。range * 2继续下一个循环。

现在只是完成了一层循环,range还要*2,继续扩大范围去排序

 外面再套上一个while循环。不过这个代码还没有结束。

 

按照这个例子,程序自然可以排序出来,但这里的问题正如对半分区间一样,并不是每个数组都可以完全对半分,总会有一些数字和数组外的数据组成了一个区间,所以程序就出来问题,比如排序10个数程序就错了,只要数据总数不是2的幂次方个就有问题。现在这个程序中间归并的过程没有问题,问题应当出现在拷贝或者开始归并之前是否缺少了判断。

为了观察越界问题,在确定好begin和end参数后打印出来看看。1-10这10个数的处理结果 

 那么如何规避越界问题?

从代码角度看,end1, begin2,end2都容易越界,begin1 = i,所以不太会越界。图中也是,三个都出现越界了。现在的越界情况可以分为三种。如果end1,越界了,那么begin2和end2肯定都越界了,比如图中[8, 11]那一行;end1没越界,begin2越界了,end2也就越界了,比如图中[8, 9]那一行;end2自己越界了,比如图中[0, 7]那一行 ,所以要针对这三个情况来处理。

以10个数为例

end1越界

发生越界了,那么修正一下区间是不是就可行了,end1如果 >= n ,那么就改成n - 1,这样begin2 ,end2也就要被改成n和n - 1了,那么begin2这个区间就一定不会进入了,只排begin1这个区间。这时候2这个区间就是[10, 9],实际上已经越界,不过下面的归并算法并不会让他进入循环,所以只是一个数字罢了,而end1是9,这样就可以避免越界问题的发生,数组所有元素也都进入了排序,这种解决办法对于后面的拷贝没有多少影响,全部排序完再拷贝(外部拷贝)或者排序一次拷贝一次(内部拷贝)都可。

还有另外一种方法,如果遇到越界了,我们就break直接退出,不排序了,这样的结果也不必担心,最终都会排序成功,但是break有一个问题,选择break的话外部拷贝就难以控制了,因为里面存在越界的时候,外部拷贝有可能就把随机值给拷贝回去了。

这里我们采用break的办法,使用修正区间的话后面两个越界问题的处理也会有相应的变化,下面再写。

begin2越界

这个比较简单,第二个区间越界了那就不归并了。直接break。

end2越界

end2越界,那我们直接修正即可。

这样最终的代码就是这样

那么如果end1越界 用修正方法,end2越界也还是用修正,begin2越界的话就不需要归并,那么修正一下,让这个区间进不去循环即可。

排序稳定性

这里会联合之前的两个复杂度,总结每个排序.

稳定性是指原始数组里同样的值的前后顺序在排序后的顺序是否正确。排序前什么顺序,排序后相对顺序仍然不变,那就是稳定,反之不稳定。

插入排序

直接插入排序:时O(N^2), 空O(1)。它稳定吗?

 直接插入排序稳定啊,插入算法里如果后面的值小于前面的,那就互换,如果相等那就跳过,继续往后走,所以相同值的相对顺序是不变的

希尔排序:时O(N^1.3), 空O(1)。它稳定吗?

希尔顺序不稳定。 因为预排序时相同的数据就不保证顺序还是和之前一样了,因为会分到不同的组。

选择排序

选择排序:时O(N^2), 空O(1)。它稳定吗?

选择排序不稳定。举一个特例,总共4个数7744.代入进函数就会发现两个4和两个7的顺序无法保证,所以选择排序其实是不稳定的。

堆排序:时O(N*logN), 空O(1), 它稳定吗?

 堆排序不稳定啊,即使放入堆的时候顺序对,但是堆排需要向下调整,这时候就无法保证了

交换排序

冒泡排序:时O(N^2),空O(1),它稳定吗?

 冒泡排序稳定。这个好理解。可以看到,两个数相等的时候就不换,所以能够稳定。

快排:时O(N*logN), 空O(logN),它稳定吗?

 

快排不稳定。快排中它不要求相对顺序,它需要一个个比较,然后交换,停下后再和key交换,所以无法保证稳定。

归并排序:时O(N*logN), 空O(N),它稳定吗? 

归并排序稳定。归并排序是在tmp中相当于取小的尾插进tmp中,那么相对顺序也就可以保证。

当然稳定的排序也可以不稳定,比如归并排序中a[begin1] < a[begin2]就不稳定了。

看一个特殊的例子

对于现在我们写的快排,如果数组里全是同一个数字,那么这个程序就很难受

 这个问题的描述就是对于大量的重复数据,在key是这个重复数据时,存在性能下降的问题。

以往快排的结果是key在中间,左边是 <= key的, 右边是 >= key的,这是两路划分。针对重复数据这个问题,有三路划分的办法,三路划分即为把整个数据分成三部分,小于key的,等于key的,大于key的,如果没有和key相等的,其实就和二路划分一样,有就放到等于key这个区间里,这块区间一直不要动,只递归大于和小于key的区间。

建三个变量,left,right,cur。

 这是第一种情况,互换后cur指向第三个数据,left指向第二个数据

 最后一个情况cur之所以是因为,right原本指向的数据并不确定是否大于小于key,所以还需要原地判断。

继续往后走,当cur大于right时整个过程就结束了。这时候整个区间就出来结果了。145  66666  87.三个区间。

代码实现 

把找key的代码放到快排函数里。 

这里还有一个问题,三数取中算法有点问题。

在力扣上会有很多特殊用例,如果按照之前的三数取中办法可能也会受到影响选到很小或很大的数字,所以改成随机数取key

 

结束。

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

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

相关文章

kubernetes的基本使用

文章目录kubernetes的基本使用1、部署方式1、部署方式的演进图2、各部署方式的特点2、架构的简单说明1、架构简图2、各组件说明1、控制平面组件&#xff08;Control Plane Components&#xff09;1、kube-apiserver2、etcd3、kube-scheduler4、kube-controller-manager5、cloud…

Apache HTTPD 换行解析漏洞

漏洞介绍&#xff1a; Apache HTTPD是一款HTTP服务器&#xff0c;它可以通过mod_php来运行PHP网页。 影响版本&#xff1a;Apache 2.4.0~2.4.29 存在一个解析漏洞&#xff1b;在解析PHP时&#xff0c;1.php\x0A将被按照PHP后缀进行解析&#xff0c;导致绕过一些服务器的安全策…

Windows中cmd命令窗口一些有用的小技巧命令

使用小功能记录 命令功能help显示所有dos命令&#xff0c;help >> cmd.txt,会把命令输出成文档altprtscreen快速截取命令行窗口esc清除当前命令行tab补全路径&#xff0c;若知道路径开头可快速补全&#xff0c;包含隐藏文件&#xff0c;但文件夹多又不知道路径开始字符时…

scrapy框架了解与使用

scrapy介绍与安装 Scrapy 是开源和协作的一个基于 Twisted 实现的异步处理爬虫框架使用纯 Python 语言编写&#xff0c;被誉为爬虫界的Django&#xff0c;Scrapy 框架应用广泛&#xff0c;常用于数据采集、网络监测&#xff0c;以及自动化测试等 Scrapy安装 mac、linux系统 …

【入门AI】利用Paddle实现简单的数字识别

梳理逻辑 整个流程 准备好Paddle的环境准备好训练样本设计模型(定义模型)训练模型模型测试 1、准备好环境 #加载飞桨和相关类库 import paddle from paddle.nn import Linear import paddle.nn.functional as F import os import numpy as np import matplotlib.pyplot as plt…

集美大学第14届蓝桥校选题解

本次比赛的出题表如下&#xff1a; 退役一年&#xff0c;勋总还是那么强呜呜呜 目录填空题[1] 十甚至九题意思路拓展[蓝桥杯] XXX 进制减法第十三届蓝桥杯C/C省赛B组 E题[2] 九大于十题意思路[3] N皇后签到题[1] JMU最强蓝人[2] 哪有赌狗一直输[3] 元胞自动机题意思路代码实…

PLC程序实例二:ModBusTCP客户端编程实例与测试方法

一、需求描述 1、设备作为服务端时&#xff0c;需要给出对应的测试方法&#xff0c;即要求 PLC 作为客户端&#xff0c;设备作为服务端&#xff0c;因此要求编写 PLC 的ModBusTCP客户端 2、先了解一下设备作为服务端的ModBusTCP网络触发业务逻辑 &#xff08;1&#xff09;设…

SQL 语法速成手册

基本概念 数据库术语 数据库&#xff08;database&#xff09;&#xff1a;保存有组织的数据的容器&#xff08;通常是一个文件或一组文件&#xff09;。数据表&#xff08;table&#xff09; &#xff1a;某种特定类型数据的结构化清单。模式&#xff08;schema&#xff09;…

JAVA SCRIPT设计模式--创建型设计模式之抽象工厂(1)

JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能&#xff0c;所以不可能像C&#xff0c;JAVA等面向对象语言一样严谨&#xff0c;大部分程序都附上了JAVA SCRIPT代码&#xff0c;代码只是实现了设计模式的主体功能&#xff0c;不代…

这俩个技巧 解决了90%的冲突

解决冲突的关键技巧 关于本书作者&#xff1a; 达纳.卡斯帕森&#xff0c;冲突调节的专家&#xff0c;尚普兰大学人际冲突专业的硕士。三次获得芭蕾舞国际协会搬的最佳舞者奖。 关于本书&#xff1a; 这是一本引导别人如何化解一段冲突&#xff0c;达成一次有效沟通的社交类…

DataX 及 DataX-Web 安装使用详解

文章目录一、DataX安装1、解压datax.tar.gz2、运行自检脚本二、Datax-Web安装1、解压DataXWeb安装包2、执行一键安装脚本3、启动服务前段时间在项目上使用了阿里的离线数据同步工具datax&#xff0c;在大批量的表同步过程中踩了一些坑&#xff0c;所以详细介绍一下&#xff0c;…

五、伊森商城 前端基础-Vue Vue脚手架原理与使用 p27

目录 Vue项目结构 一、使用vue脚手架进行模块化开发 1、main文件 1.1、首先new Vue创建了一个vue实例&#xff0c;这个实例挂载了index.html中的app元素 1.2、使用了路由&#xff0c;这个路由是简写的写法 1.3、components使用了一个组件叫App 1.4、最终渲染 2、App.vu…

卷积神经网络相关模型

卷积神经网络相关模型1. CNN架构2. CNN架构模型2.1LeNet模型2.2Alexnet模型2.3VGG16模型2.3.1 使用多层小卷积核代替一层大的卷积核优点2.3.2 使用1*1卷积核优点2.3.2 模型特点卷积神经网络基本概念相关知识连接 卷积神经网络基本概念相关知识连接 1. CNN架构 模型分为2部分【…

ubuntu1804在rviz中显示kitti数据集的2D检测框和激光雷达的3D检测框

之前所做的工作参考上篇博客ubuntu1804发布kitti数据集的gps资料,imu资料(包含发布图片,点云过程)_FYY2LHH的博客-CSDN博客 本次将详解如何在ros播放的kitti数据集上作出检测框,首先需要知道的是对于kitti数据集中的每一帧都必须提前进行标注,而这个工作已经被别人完成了…

42. Python range函数—生成器函数

42. range函数—生成器函数 文章目录42. range函数—生成器函数1. 什么是range( )函数2. 回顾列表切片的语法3. range( )函数的语法3. range函数实操3.1 只有1个参数3.2 有2个参数3.3 有3个参数3.4 步长为负数4. list不能完全替代range5. 总结1. 什么是range( )函数 range[reɪ…

基于遗传算法在机器人路径规划中的应用研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

第十七章 优先队列优化Dijkstra算法

第十七章 优先队列优化Dijkstra算法一、普通dijkstra算法的缺陷1、选出最小距离的过程&#xff1a;2、松弛所有点的过程&#xff1a;二、如何优化1、代码模板&#xff08;1&#xff09;问题&#xff1a;&#xff08;2&#xff09;模板&#xff1a;2、详细解读三、优化分析1、使…

5G赋能行业应用,助推数智化转型!

导语 | 5G 技术的蓬勃发展推动其行业应用的巨轮乘风破浪、扬帆启航&#xff0c;5G 技术不断落地布局于各行各业&#xff0c;基础建设也不断完善&#xff0c;5G to B 的时代已经到来。此次&#xff0c;我们邀请到了中国电信研究院工业互联网技术研发部主任、腾讯云 TVP 谭华老师…

知识图谱-KGE-语义匹配-双线性模型(打分函数用到了双线性函数)-2014:TATEC

【paper】 Effective Blending of Two and Three-way Interactions for Modeling Multi-relational Data 【简介】 本文是法国 Antoine Bordes 团队发表在 ECML-PKDD 2014 上的工作&#xff0c;提出了 TATEC&#xff08;Two and Three-way Embeddings Combination&#xff09;…

ERP+MES集成管理系统重要性有哪些?

随着企业信息化观念的提升&#xff0c;管理方式也愈来愈信息化&#xff0c;因此以信息化推动企业的不断发展趋势已变成企业存活和发展的主要核心理念。其中E&#xff32;P 系统和 MES 系统在企业发展和改革中起着非常重要的作用。当各种信息化系统在企业内各个部门顺利执行的同…