排序算法三:堆排序基本原理以及Python实现

1. 基本原理

堆排序就是利用堆的特性进行一个无序序列的排序工作。

堆的特点

堆分为最大堆和最小堆,其实就是完全二叉树

  1. 最大堆要求节点的元素都要不小于其孩子

  2. 最小堆要求节点元素都不大于其左右孩子

两者对左右孩子的大小关系不做任何要求,其实很好理解。

有了上面的定义,我们可以得知,处于最大堆的根节点的元素一定是这个堆中的最大值。

其实我们的堆排序算法就是抓住了堆的这一特点,每次都取堆顶的元素,将其放在序列最后面,然后将剩

余的元素重新调整为最大堆,依次类推,最终得到排序的序列。

基本思想

  1. 将初始待排序关键字序列(a1,a2,,an)构建成大顶堆,此堆为初始的无序区

  2. 将堆顶元素a[1]与最后一个元素a[n]交换,此时得到新的无序区(a1,a2,,an1)和新的有序区(an)

  3. 由于交换后新的堆顶a[1]可能违反堆的性质,因此需要对当前无序区(a1,a2,,an1)调整为新堆,然后再次将a[1]与无序区最后一个元素交换,得到新的无序区(a1,a2,,an2)新的有序区(an1,an2)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

一个例子

这里有一个无序的序列,[16,7,3,20,17,8]

首先构造一个二叉树:

这里写图片描述

然后依据构造的二叉树,从下至上调整,得到一个初始化的最大堆。

这里写图片描述 这里写图片描述

再讲堆顶的数和堆底的数互换。

这里写图片描述

但是,此时的堆可能不符合要求,需要再从新调整:

这里写图片描述这里写图片描述

再重复,将堆顶和堆底互换(当然了,在之前,堆的大小要减1)

这里写图片描述

又一次进行调整:

这里写图片描述这里写图片描述

重复,将堆顶和堆底互换(当然了,在之前,堆的大小又要减1)

这里写图片描述

再调整:

这里写图片描述

再换:

这里写图片描述

再调整:

这里写图片描述

再换:
这里写图片描述

到这,一个堆排序就完成了,最终得到一个最小堆。

2. Python 实现

程序

#定义一个对单一节点的父节点以及其孩子大小交换的函数
def initialMaxHeap(a,startIndex,endIndex):leftChildIndex=2*startIndex+1 #父节点为i,左边孩子的位置为2*i+1#判断左边孩子是否有右边的孩子if leftChildIndex+1<=endIndex and a[leftChildIndex+1]>a[leftChildIndex]:leftChildIndex+=1       if a[leftChildIndex]>a[startIndex]:#左右孩子值大于父节点的值的时候,交换,使得这个二叉树的最大值位于父节点上temp=a[startIndex]a[startIndex]=a[leftChildIndex]def myHeapSort(a):#a是要排序的序列listLength=a.__len__()while True:if listLength==1:break;finalNodeHavingChild=(listLength)//2-1 #寻找最下一层的父节点#从下到上调整堆for i in range(finalNodeHavingChild,-1,-1):#print(a[i])initialMaxHeap(a,i,listLength-1)#将堆顶的数换到堆底temp=a[0]a[0]=a[listLength-1]a[listLength-1]=temp#这个调整之后,可能不满足最大堆的定义,需要再从上到下再调整一次#从上到下调整堆for j in range(0,finalNodeHavingChild+1):#print(a[j])initialMaxHeap(a,j,listLength-1)#将堆的数量减少listLength-=1return a    def generatingRandomNumber(sampleNumber,lower,upper):#sampleNumber :是生成的随机序列的长度#lower和upper分别是生成随机序列的下限与上限#最后,函数会返回一个随机的无序的序列a。import randoma=[]aSize=a.__len__()while 1:aSize=a.__len__()if aSize>=sampleNumber:breakelse:temp=int(random.randint(lower,upper))a.append(temp)return aif __name__=="__main__":a=generatingRandomNumber(20,1,100)print()print('the sequence before sorting is:\n')print(a)print()print('the sequence after sorting is:\n')print(myHeapSort(a))

结果为:

这里写图片描述

结果正确!!!

排序动态图
这里写图片描述

3. 时间复杂度分析

在构建堆(初始化大顶堆)的过程中,完全二叉树从最下层最右边的非终端结点开始构建,将它与其孩子进行比较和必要的互换,对于每个非终端结点来说,其实最多进行两次比较和一次互换操作,因此整个构建堆的时间复杂度为: O(n)。大概需进行 n22=n 次比较和 n2 次交换。

在正式排序时,n 个结点的完全二叉树的深度为log2n+1并且有 n个数据则需要取 n1 次调整成大顶堆的操作,每次调整成大顶堆的时间复杂度为O(log2n)。因此,重建堆的时间复杂度可近似看做: O(nlog2n)

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

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

相关文章

spring jms 消息_Spring JMS,消息自动转换,JMS模板

spring jms 消息在我的一个项目中&#xff0c;我应该创建一个消息路由器&#xff0c;就像所有路由器一样&#xff0c;它应该从一个主题获取JMS消息并将其放入另一个主题。 该消息本身是JMS文本消息&#xff0c;实际上包含XML消息。 收到消息后&#xff0c;我还应该添加一些其他…

排序算法四:归并排序基本原理以及Python实现

1. 基本原理 归并排序建立在归并操作上的一种算法。该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。归并排序是将两 个已经有序的序列合成一个有序的序列的过程。 因此&#xff0c;对于一个待排序的序列来说&#xff0c;首先要将其进行…

如何将JAR添加到Jetbrains MPS项目

Jetbrains MPS是创建DSL的绝佳工具。 我们喜欢它&#xff0c;并在我们的咨询工作中定期使用它。 因此&#xff0c;我们之前已经写过关于Jetbrains MPS的文章 。 作为投影编辑器&#xff0c;您可以轻松创建可通过图形界面或数学公式之类使用的DSL。 尽管所有这些功能都需要做一…

Python 3实现k-邻近算法以及 iris 数据集分类应用

前言 这个周基本在琢磨这个算法以及自己利用Python3 实现自主编程实现该算法。持续时间比较长&#xff0c;主要是Pyhton可能还不是很熟练&#xff0c;走了很多路&#xff0c;基本是一边写一边学。不过&#xff0c;总算是基本搞出来了。不多说&#xff0c;进入正题。 1. K-邻近…

spring mvc 异步_DeferredResult – Spring MVC中的异步处理

spring mvc 异步DeferredResult是一个可能尚未完成的计算的容器&#xff0c;它将在将来提供。 Spring MVC使用它来表示异步计算&#xff0c;并利用Servlet 3.0 AsyncContext异步请求处理。 简要介绍一下它是如何工作的&#xff1a; RequestMapping("/") ResponseBod…

切换表达式到Java吗?

已创建一个标题为“ Java语言的开关表达式”的JEP草案 。 当前的“摘要”状态为&#xff1a;“扩展switch语句&#xff0c;以便可以将其用作语句或表达式&#xff0c;并改善switch处理null的方式。 这些将简化日常编码&#xff0c;并为在switch使用模式匹配做好准备。” 除了启…

WildFly Kubernetes exec探针

活动和就绪探针会告诉Kubernetes吊舱是否正在运行并准备进行一些工作。 企业应用程序可以通过HTTP探测应用程序的状态。 如果没有暴露HTTP端点&#xff0c;Kubernetes也可以通过执行命令进行探测。 WildFly附带了有用的jboss-cli.sh 。 此CLI检索有关服务器和部署状态的信息&a…

FPGA硬件学习基础知识点总结(1)

FPGA硬件学习基础知识点总结&#xff08;1&#xff09;锁存器与触发器 总结一下数电&#xff0c;FPGA的一些基础知识&#xff0c;涉及到硬件电路的设计。主要是记录自己的学习过程。 锁存器与触发器 锁存器&#xff08;latch&#xff09;&#xff1a;锁存器是电平触发的存储单…

ejb java_EJB继承与Java继承不同

ejb java尽管EJB继承有时使用Java继承&#xff0c;但事实并非总是如此。 就像您在我以前的文章中可以读到的那样 &#xff0c;EJB不必实现任何接口即可公开业务接口。 反之亦然-仅仅是因为EJB实现了某个接口或扩展了其他EJB&#xff0c;并不意味着它公开了全部或任何视图。 假…

UART原理

UART原理 通用异步收发传输器&#xff08;Universal Asynchronous Receiver / Transmitter)&#xff0c;通常称作UART&#xff0c;是一种异步收发传输器&#xff0c;是电脑硬件的一部分。将资料由串行通信与并行通信间作传输转换&#xff0c;作为并行输入成为串行输出的芯片&am…

Java 9:流API的增强

Java 9向Stream接口添加了4种新方法&#xff1a; 1. dropWhile dropWhile方法类似于skip方法&#xff0c;但使用Predicate而不是固定的整数值。 当Predicate为true时&#xff0c;它将从输入流中删除元素。 然后将所有剩余的元素传递到输出流。 例如&#xff1a; IntStream.ra…

AttributeError: module 'tensorflow' has no attribute 'placeholder'等一系列tensorflow版本导致的问题

新人tensorflow2.1版本导致程序我无法运行最简单的办法 法1 tensorflow.compat.v1 import tensorflow.compat..v1 as tf tf.disable_v2_behavior() 亲测不好用 法2 卸载2.1&#xff0c;安装老版本 在Terminal界面输入 pip uninstall tensorflow接着输入Y确定卸载。 安装t…

正则表达式 guava_带有正则表达式模式的Google Guava Cache

正则表达式 guava最近我看到了一个关于Google Guava的不错的介绍 &#xff0c;我们在我们的项目中得出结论&#xff0c;使用它的缓存功能真的很有趣。 让我们看一下regexp Pattern类及其编译功能 。 在代码中我们经常可以看到&#xff0c;每次使用正则表达式时&#xff0c;程序…

word中一直提示校对错误,如何关闭当前文档校对功能

关闭当前文档校对功能 文件>选项>校对>例外项&#xff0c;选中两个&#xff0c;如图 对比效果&#xff1a;

微信小程序开发学习记录01

微信小程序结构 根目录 app.js&#xff1a;小程序逻辑文件&#xff08;必须&#xff09; app.json&#xff1a;小程序配置文件&#xff08;必须&#xff09; app.wxss&#xff1a;全局公共样式文件&#xff08;非必须&#xff09; pages 组成小程序的多个页面&#xff0c…

Java Optionals获得更具表现力的代码

我们中任何人使用允许空引用的语言进行编程时&#xff0c;都会遇到尝试取消引用一个引用时发生的情况。 无论是导致segfault还是NullPointerException&#xff0c;它始终是一个错误。 托尼霍尔将其描述为他十亿美元的错误 。 当函数向客户端的开发人员未预料到的客户端返回空引…

Atom使用方法(快捷键,插件,汉化)

Atom文本编辑软件 使用方法 常用快捷键 Ctrl Shift M &#xff1a;打开markdown调试窗口 Crtl m&#xff1a;相应括号之间&#xff0c;html tag之间等跳转 Crtl Alt B&#xff1a; 格式化代码&#xff08;需要安装atom-beautify&#xff09; Crtl &#xff1a;调起CLI…

将测微仪与Spring Boot 2一起使用

这是快速入门&#xff0c;介绍了如何使用出色的Micrometer库来检测基于Spring Boot 2的应用程序并在Prometheus中记录指标 介绍 Micrometer在各种监视工具提供的客户端库上提供了基于Java的外观。 以Prometheus为例&#xff0c;如果我要将Java应用程序与Prometheus集成&#…

学习笔记整理

毕设学习笔记整理说明Python和Pycharm使用方面因网络问题导致pycharm安装第三方库失败的解决办法将python程序打包为exe程序pyinstallerpy2exepycharm取消缩进Python函数方面python中 if __name__ __main__: 的作用与意义cv2.resize的用法只读取图像的单通道数值最值索引图像增…

与Maven的集成测试

用Maven实施单元测试是很普通的事情&#xff0c;我们大多数人都熟悉项目结构以及单元测试所在的位置。 但是&#xff0c;集成测试是一种不同的情况&#xff0c;大多数情况下它们具有完全不同的要求。 例如&#xff0c;可以让您的单元测试在内存数据库中的h2上运行&#xff0c;…