堆排序的实现

在上一篇博客中,介绍了堆的实现,现在来介绍一下堆排序。

一.打印有序:

现在先给一个无序的数组,现在我们利用我们实现的堆的功能先完成一下打印排序:

在for循环里是一个建堆的过程,每来一个数据就放入堆中。

在调试中不难发现,在经过建堆过程之后,我们在这里建的是小堆:

建立小堆完之后,此时我们要完成打印上的排序,在这里就利用循环不断利用取堆顶数据的函数,和删除堆顶数据的函数(利用了向下调整算法在删除后还是保持小堆的性质),这样就完成了打印排序:

上面实现了从小往大的打印排序,现在要建大堆,来实现从大往小打印排序:

这里只需要改一下向上和向下算法里,孩子节点与父亲节点的比大小关系即可:

将这两个大小比较换一下即可,这样就变成了大堆,现在就完成了降序:

所以这就是为什么HPPop是删除堆顶的数据了,这样不管是小堆还是大堆这样就能实现排序,每次删除都能找到次小或者次大的值。在介绍二叉树的性质时,我们推导过,假设这个数是N个节点,则高度为:

所以这样排序的时间复杂度就是log2(N),而冒泡排序的时间复杂度是N^2,所以这个排序是效率非常高的。

二.真正实现堆排序:

这里如果给你一个数组,而我们如果再去利用我们封装好的堆的初始化之类的函数的时候,这样我们就会开辟新的空间,所以我们实现堆的排序,直接就是利用向上调整算法,直接将数组调成堆的样子,这也是为什么在写向上和向下调整算法时,传的是数组的地址,而不是传数据结构。

而这里循环从数组的1的位置开始,原因是这里直接将数组0的位置直接看成堆,然后向下插入,再向下调整。

现在来试一下,建堆是否成功:

这里也是建大堆成功。

这里虽然建大堆成功,但我们想要降序时,堆顶的数据就不能动了,此时我们要找出次大的数据,这里我们只能将剩下的数看成一个堆:

左边是每删数据前,后面是要找次大的数据把剩下的数据看成堆的情况,但是我们可以发现,原本父子关系的节点,现在变成了兄弟节点,关系变混乱了,所以这里不是大堆了,不管用向上还是向下的算法都不行了,这里可以重新建堆,但是这里会导致复杂度上去,代价太大了,所以不用这种方法。

所以在这里我们要考虑降序建大堆还是小堆,升序建大堆还是小堆:

这里直接说结果,降序去建小堆,升序去建大堆。

先来解释降序建小堆怎么玩:

首先小堆建完,这里我们要降序,因为是小堆,所以最小的数在堆顶,此时我们就将堆顶的数与最后一个数进行交换,然后将最后一个数覆盖掉(不是真覆盖),此时在利用向下调整算法,找到次小的那个数据,然后再与倒数第二个数交换,然后再利用向下调整算法,整个一套流程下来,数组里的值的位置就发生了变化,此时也实现了降序。

在这里我们可以算一下这样堆排序的复杂度,每调整一次是二叉树的高度logN,一共有N个数据,所以其复杂度就是logN*N,所以这样排序效率更高。

在向上向下调整算法中,小于就是建小堆,大于就是大堆。

在上面的叙述中先前用的都是向上调整建堆,有没有别的建堆方法呢,这里我们还有向下调整建堆,当左子树右子树都是大堆或者小堆时可以用向下调整算法,但是如果不是呢

这里有个方法就是倒着建堆:

思路就是先找到最后一个叶子节点在这里就是9,然后找到其父亲节点也就是5,然后先进行调整,调整完过后圈1里的那个数据就成堆了,再次调整,5减减之后就是另一个父亲节点1,再给1那里建堆也就是圈2,再减减找到另一个父亲节点8,再次建堆,建完之后就是圈3,再减减父亲节点就是2,因为上面已经将父亲节点2下面的孩子节点已经调成了堆,所以直接用向下调整算法调整大圈里的数据,也就是圈4,最后就调整整个树就是,这样堆就完成了,这个向下调整建堆的时间复杂度是O(N).效率更高

总结:堆排序是脱离了堆的结构,只是用了向上和向下调整算法,并且堆排序的时间复杂度是O(logN*N)和O(N),而冒泡排序时间复杂度是O(N*N),当数据很大时,堆排序的时间效率更高,更快,比冒泡排序好很多。

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

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

相关文章

linux进程的加载和启动过程分析

我们的源代码通过预处理,编译,汇编,链接后形成可执行文件,那么当我们在终端敲下指令$ ./a.out argv1 argv2 后,操作系统是怎么将我们的可执行文件加载并运行的呢? 首先知道,计算机的操作系统的启动程序是写死在硬件上的,每次计算机上电时,都将自动加载启动程序,之后…

python第五次作业

1.请实现一个装饰器,每次调用函数时,将函数名字以及调用此函数的时间点写入文件中 # 导入datetime模块,用于获取当前时间并格式化输出 import datetime# 定义一个装饰器工厂函数log_funcName_time,它接受一个参数time def log_fu…

红外听力教学考试系统-红外语音听力广播在大学英语四六级听力考试中应用

红外听力教学考试系统-红外语音听力广播在大学英语四六级听力考试中的应用 由北京海特伟业科技有限公司任洪卓发布于2024年6月1日 红外语音听力广播(即红外听力教学考试系统)在英语四六级听力考试的应用正日益凸显出其重要性和优越性。在当前的高等教育…

xcode删除依赖包package,删除不必要的依赖项

点击项目,然后点击PROJECT项里面的Package DepenDependencies: 选中一个依赖项,然后点击减号,就可以把依赖项删除掉了,左侧项目下面的Package已经没有了这个依赖项 TARGET下面的package也要删除:在这里删除…

大数据分析统计

大数据分析统计 from datetime import datetimeimport pandas as pd import matplotlib.pyplot as pltpm25files [PM2.5_2021.csv, PM2.5_2022.csv, PM2.5_2023.csv] pm10files [PM10_2021.csv, PM10_2022.csv, PM10_2023.csv]def read_csv_file(files):# 每个文件都有表头…

C++之类(class)的三种成员修饰符(public、private、protected)总结

1、背景介绍 在C中,类(class)中成员的三种访问修饰符(access specifiers)用于控制类的成员(属性和方法)的访问权限。这些修饰符决定了类成员在类的外部和内部是否可以被访问。以下是这三种访问…

macOS上编译android的ffmpeg及ffmpeg.c

1 前言 前段时间介绍过使用xcode和qt creator编译调试ffmepg.c,运行平台是在macOS上,本文拟介绍下android平台如何用NDK编译链编译ffmepg库并使用。 macOS上使用qt creator编译调试ffmpeg.c macOS上将ffmpeg.c编译成Framework 大体思路: 其…

信息学奥赛初赛天天练-18-挑战程序阅读-最长公共子序列、字符串与数组越界的巧妙应用

PDF文档公众号回复关键字:20240601 1 2023 CSP-J 阅读程序2 阅读程序(程序输入不超过数组成字符串定义的范围:判断题正确填√,错误填;除特殊说明外,判断题1.5分,选择题3分,共计40分&#xff…

Dijkstra求最短路篇二(全网最详细讲解两种方法,适合小白)(python,其他语言也适用)

前言: Dijkstra算法博客讲解分为两篇讲解,这两篇博客对所有有难点的问题都会讲解,小白也能很好理解。看完这两篇博客后保证收获满满。 第一篇博客讲解朴素Dijkstra算法Dijkstra求最短路篇一(全网最详细讲解两种方法,适合小白)(p…

计网ppt标黄知识点整理第(2)章节——谢希仁版本、期末复习自用

物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体。4 个特性: 机械特性:指明接口所用接线器的形状和尺寸、引线数目和排列、固定和锁定装置等。 电气特性:指明在接口电缆的各条线上出现…

基于Springboot驾校预约平台小程序的设计与实现(源码+数据库+文档)

一.项目介绍 系统角色:管理员、教练、学员 小程序(仅限于学员注册、登录): 查看管理员发布的公告信息 查看管理员发布的驾校信息 查看所有教练信息、预约(需教练审核)、评论、收藏喜欢的教练 查看管理员发布的考试信息、预约考试(需管理…

2024年东北师范CCPC

文章目录 A.Paper WateringB.nIM gAMEE.Checksum A.Paper Watering 思路:题目说有平方和开方两种操作,如果这个数是平方数,那么它开方之后就只能开方,如果平方的话就重复了,反之就有开方和平方两种操作。 代码如下 //…

为了方便看公众号文章,我搭建了个博客,在线看公众号所有历史文章,想看哪天的文章一秒就能找到

公众号没有个网页版的文章列表,只能在电脑和手机客户端看,想看之前的历史文章只能一直往下拉,想找某篇文章非常费劲。 为了方便看公众号文章,我搭建了个博客,博客地址https://sushengbuhuo.github.io/blog &#xf…

通过 SFP 接口实现千兆光纤以太网通信1

基于米联客ARTIX-7 系列开发板及其开发手册。 总体实现框图如下: SFP 接口 SFP 信号定义如下图所示。 Tri Mode Ethernet MAC 设置 由于使用千兆通讯,因此将速率设为 1Gbps。如下图所示。 首先,由于该 IP 需要与 IP 核 1G/2.5G Ethernet …

基于IoTDB 平台的学习和研究

Apache IoTDB(物联网数据库)是一个针对物联网领域的高性能原生数据库,适用于数据管理和分析,并可在边缘计算和云端部署。由于它轻量级的架构、高性能和丰富的功能集,以及与Apache Hadoop、Spark和Flink的深度集成&…

数据管理知识体系必知的14张语境关系图

近期对数据管理知识体系中的语境关系图进行了整体学习梳理,总共有14张图,具体如下,供大家参考。应该说语境关系图和环境因素六边形图是各有侧重、互为补充关系。语境关系图是环境因素六边形图的细化,描述了每个知识领域中的细节,相当于数据管理的微观视角, 包括与人员、 …

kali中切换python版本

kali中切换python版本 在日常使用的过程中,可以通过一些工具来做打靶环境,或者工具的启动,都和python关联,而有时存在工具安装,或者运行的时候出现报错,这时候极大可能是因为我们本地的kali中python的版本不…

Android Studio | 小白如何运行别人的安卓项目

目录 Step1:正确地打开项目 Step2:AS 同步时报错 Step3:同步完成后启动 Step4:启动成功 说明:本文简称 Android Studio 为 AS Step1:正确地打开项目 重点:确认好项目的根目录是哪个目录&am…

进程与线程(三)

进程与线程(三) 进程间通信传统间的进程间通信机制无名管道无名管道的特征无名管道的创建父子进程通信测试管道的大小管道读写易出现的问题 有名管道创建有名管道有名管道的写端代码有名管道的读端代码 信号信号的特征产生信号硬件来源软件来源发送信号的…

【第1章】SpringBoot实战篇之注册接口

文章目录 前言一、代码部分1. User2.UserMapper13. UserSerivce4. UserController15. Result 二、测试1.注册2.再次注册 总结 前言 下面介绍用户注册接口。 一、代码部分 1. User package org.example.springboot3.bigevent.entity;import com.baomidou.mybatisplus.annotat…