网站首页 > java教程 正文
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
其大致比较执行图为:
定义
堆排序其实是利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
如:
n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):
(1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n/2),当然,这是小根堆,大根堆则换成>=号。k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
堆数据结构分析
高度:堆可以被看成是一棵树,结点在堆中的高度可以被定义为从本结点到叶子结点的最长简单下降路径上边的数目;定义堆的高度为树根的高度。我们将看到,堆结构上的一些基本操作的运行时间至多是与树的高度成正比,为O(lgn)。
堆节点的访问:通常堆是通过一维数组来实现的。在数组起始位置为0的情形中:父节点i的左子节点在位置(2*i+1);父节点i的右子节点在位置(2*i+2);子节点i的父节点在位置floor((i-1)/2);
堆的操作:在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点。创建最大堆(Build_Max_Heap):将堆所有数据重新排序堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
堆的基本排序步骤为:
Java实现源码分析
首先创建一个方法表示堆排序,参数为待排序数组
在排序之前,我们首先要对当前数组建立一个最大堆或者最小堆
然后迭代一次迭代前(n-1)个数,继续奖励最大堆或者最小堆,依次迭代,直到剩下长度为1
那么如何建立最大堆呢(最小堆相反比较即可),源码如下:
因为只需要对非叶子节点做最大堆构建,所以建立最大堆的cao做实际上是[0, n/2]之间的节点。
该方法为对序号为i的节点做最大堆的构建,那么该节点的左子节点为:i*2-1, 右子节点为:i*2
需要检验左右子节点是否存在。
当发现构造的当前堆的根节点发生变更时,需要再次对其父节点做最大堆的重新构造。
我们可以发现,堆算法巧妙的运用了数组和二叉树数据结构关系以及堆数据结构的性质来实现的。只要你懂得最大堆、最小堆的性质,以及如何构建一个最大堆和最小堆,那么该算法应该很快能实现
算法分析
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。
平均性能:O(N*logN)。
其他性能:由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1).
它是不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)
完整代码可参考: https://zhuanlan.zhihu.com/p/25566353
如果这对你有用,粉我吧,每天都有干货哦
历史相关内容
排序算法 - 希尔排序
猜你喜欢
- 2024-11-03 java桶式排序算法(桶排序代码)
- 2024-11-03 算法篇:Java实现九种排序算法1:插入排序之后直接插入排序
- 2024-11-03 十大经典排序算法最强总结(含JAVA代码实现)
- 2024-11-03 JAVA从零开始之排序算法(spicyChicken盘点)
- 2024-11-03 JAVA十大排序算法之基数排序详解(java的排序)
- 2024-11-03 十大经典《排序算法》你还记得多少?
- 2024-11-03 Java排序算法——选择排序(java的选择排序)
- 2024-11-03 java实现10种排序算法(java十大排序算法)
- 2024-11-03 JAVA十大经典排序算法(java常见排序算法)
- 2024-11-03 常用排序算法总结(常用排序算法总结)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)