当前位置: 首页 > 编程日记 > 正文

排序算法总结之堆排序

一,堆排序介绍

堆是一个优先级队列,对于大顶堆而言,堆顶元素的权值最大。将 待排序的数组 建堆,然后不断地删除堆顶元素,就实现了排序。关于堆,参考:数据结构--堆的实现之深入分析

下面的堆排序算法将数组中的元素从小到大排序,用大顶堆来实现。

二,堆排序算法分析

现给定了一维数组,需要将数组中的元素使用堆排序。首先,得创建一个堆,可以在这个给定的一维数组上建堆。 对N个元素 建堆的时间复杂度为O(N)

堆排序具体的细节实现有两种方式:一种方式是将堆顶元素删除后,放到一个辅助数组中,然后进行堆调整使之成为一个新堆。接下来,继续删除堆顶元素,直至将堆中所有的元素都出堆,此时排序完成。这种方式需要一个额外的辅助空间O(N)

另一种方式是:将每次删除的堆顶元素放到数组的末尾。因为,对于堆的基本操作 delMin/delMax 而言(delMin针对的是小顶堆,delMax针对的是大顶堆,原理一样)是将堆中的最后一个元素替换堆顶元素,然后向下进行堆调整。因此,可以利用这个特点将每次删除的堆顶元素保存在数组末尾,当所有的元素都出堆后,数组就排好序了。这种方式不需要额外的辅助空间,空间复杂度为O(1)

三,堆排序算法实现

 1 public class HeapSort {
 2     
 3     public static <T extends Comparable<? super T>> void heapSort(T[] arr){
 4         //build heap
 5         for(int i = arr.length/2 - 1; i >= 0; i--)
 6             percDown(arr, i, arr.length);
 7         
 8         
 9         for(int i = arr.length - 1; i >= 0; i--)
10         {
11             swapReference(arr, 0, i);//delete Max
12             
13             percDown(arr, 0, i);// 从根开始向下堆调整
14         }
15     }
16     
17     private static <T extends Comparable<? super T>> void swapReference(T[] arr, int from, int to){
18         T tmp;
19         tmp = arr[from];
20         arr[from] = arr[to];
21         arr[to] = tmp;
22     }
23     
24     //求解 i 的左孩子
25     private static int leftChild(int i){
26         return 2*i + 1;
27     }
28     
29     /**
30      * 
31      * @param arr 存储堆的一维数组
32      * @param i 从 i 位置开始进行向下堆调整
33      * @param n 堆中元素的个数(不是数组的长度)
34      */
35     private static <T extends Comparable<? super T>> void percDown(T[] arr, int i, int n){
36         int child;
37         T tmp;//保存当前待调整的结点,当找到了合适的位置后,需要将之放入到合适位置,以保持堆序性质
38         
39         for(tmp = arr[i];  leftChild(i) < n; i = child)
40         {
41             child = leftChild(i);
42             if(child != n-1 && arr[child].compareTo(arr[child+1]) < 0)
43                 child++;//右孩子更大
44             if(tmp.compareTo(arr[child]) < 0)
45                 arr[i] = arr[child];//父节点下移
46             else
47                 break;//父节点比左右孩子都大时,不需要再向下移动了
48         }
49         arr[i] = tmp;//将节点放入合适的位置
50     }
51     
52     //for test purpose
53     public static void main(String[] args) {
54         Integer[] arr = {31,41,59,26,53,58,97};
55         heapSort(arr);
56         for (Integer i : arr) {
57             System.out.print(i + " ");
58         }
59     }
60 }

有几个细节地方解释一下:

①在第3行的heapSort方法中,第5-6行是建堆操作,因为数组中的元素是从下标0开始存储的,故最后一个非叶子结点的下标为:arr.length/2 - 1

②第9-14行是进行堆排序的操作。swapReference方法相当于删除堆顶元素,因为它把堆顶元素交换到数组的末尾去了,此时堆顶元素不再是最大值(大顶堆)。删除了堆顶元素之后,就要进行堆调整以保持堆序性质,故percDown方法 完成向下进行堆调整的功能。

③在堆调整的过程中,需要求解某个结点的左 右孩子结点的位置。故有一个leftChild方法用来求解左孩子的位置(注意元素是从数组下标0开始存储的)

④percDown方法实现向下的堆调整功能。第37行  tmp 变量 保存当前待调整的结点,当找到了合适的位置后,需要将之放入到合适位置,以保持堆序性质。对于建堆而言,待调整的结点是从 非叶结点 开始,直至根的那些结点。对于删除堆顶元素而言,则总是从堆顶元素起开始调整(待调整的结点是根)

⑤第39行的for循环实现得非常巧妙,首先tmp保存当前待调整的结点 arr[i],然后判断 arr[i] 是否有左孩子,如果有左孩子的话,又在第42行的if语句中判断它是否还有右孩子(child != n-1),然后左右孩子进行比较,child记录下权值大的那个孩子。

⑥第44-45行的if语句完成的功能是:将权值大的孩子与父结点比较,如果父结点的权值小,则需要将那个较大的孩子上移到父结点的位置(也相当于父结点下移到孩子的位置)

如果父结点的权值大,已经找到了合适的位置了。说明不需要再进行堆调整了,执行else break;

⑦第49行,就待调整的结点入到到合适的位置i处。整个过程并没有用交换操作,而是用的是赋值操作来隐式地实现了交换操作完成的功能,这是一个优化。

四,堆排序算法复杂度分析

对N个元素建堆的时间复杂度为O(N),删除堆顶元素的时间复杂度为O(logN),尽管随着元素的不断删除,堆的调度越来越小,但是总的而言,删除堆所有元素的时间复杂度为O(NlogN)

故堆排序的时间复杂度为O(NlogN),空间复杂度为O(1)

其实,堆排序是一个非常稳定的算法,最坏和平均情况下的时间复杂度都为O(NlogN)

此外,对于堆排序而言,数据的初始顺序对它的复杂度没有影响。不管数组初始时就是有序的还是逆序的,它都会先建堆,变成了堆序的性质。

五,参考资料

排序算法总结之插入排序

排序算法总结之快速排序

排序算法总结之归并排序

各种排序算法的总结

相关文章:

Hessian通信案例(java)

个人博客&#xff1a; 戳我,戳我 前言 由于工作的原因&#xff0c;接触到了hessain,项目需要做hessain和xml之间的报文转换。但是对于hessian是个什么东西一头雾水。于是接下来的时间了解了hessain协议的序列化规则以及hessian协议进行通信的方式。这篇文章是在完成了这个模块…

VDI序曲二十一 APP-V 4.6 SP1服务器端部署

APP-V是微软应用程序虚拟化除RemoteApp以外非常棒的另一种应用程序虚拟化&#xff0c;此应用程序虚拟化是把搭开应用程序消耗的资源放在前端&#xff0c;应用程序虚拟化主要解决的还是软件兼容性问题和保护软件资产问题&#xff0c;同时让用户无需安装就可以绿色使用的手段&…

绝悟之后再超神,腾讯30篇论文入选AI顶会ACL

作者 | 马超责编 | Carol出品| AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;封图 | CSDN 付费下载于东方 IC近日&#xff0c;国际计算语言学协会年会ACL在官网(https://www.aclweb.org)公布了2020年度的论文收录名单&#xff0c;其中腾讯共有30篇论文入选&…

mac中用命令行运行mysql

1&#xff0c;安装mysql 在mysql的官方网站下载 mysql 5.5.23 http://www.mysql.com/downloads/mysql/&#xff0c;根据我的机器的配置情况选择了64bit版本。 2&#xff0c;命令行中启动mysql 安装的位置在/usr/local/mysql 于是做了一个别名&#xff1a; $alias mysql/usr/loc…

Hessian源码分析(java)

个人博客&#xff1a; 戳我&#xff0c;戳我 先扯一扯 前一篇博文Hessian通信案例(java)简单实现了Java版的Hessian客户端和服务端的通信&#xff0c;总体看来&#xff0c;实现起来比较简单&#xff0c;整个基于Hessian的远程调用过程也显得很方便。但是知其然还要知其所以然&…

必读!53个Python经典面试题详解

作者 | Chris翻译 | 苏本如&#xff0c;编辑 | 夕颜题图 | 视觉中国出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;本文列出53个Python面试问题&#xff0c;并且提供了答案&#xff0c;供数科学家和软件工程师们参考。不久前&#xff0c;我作为“数据科学家”开始担…

Microsoft Web 平台安装程序 (Web PI) Microsoft Web Platform Installer

Microsoft Web 平台安装程序 3.0 (Web PI) 是一款免费的工具&#xff0c;使用它可以获得 Microsoft Web 平台的最新组件&#xff08;包括 Internet Information Services (IIS)、SQL Server Express、.NET Framework 和 Visual Web Developer&#xff09;。Web PI 的内置Window…

Linux Shell 脚本限制ssh最大用户登录数

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/1670233 我撰写本文原来的意图是想把“复制SSH渠道”和"copy SSH Session"这样的功能从远程s…

hessiancpp编译和使用(C++版)

个人博客&#xff1a;戳我&#xff0c;戳我 许下的承诺 前两篇博客Hessian通信案例(java)和Hessian源码分析(java)介绍了Java版的hessian的使用以及源码分析。当时也说过打算写一下C版的hessian的使用和源码分析&#xff0c;现在就是兑现承诺的时候了。其实我项目中实际用到的…

美国AI博士一针见血:Python这样学最容易成为高手!

我见过市面上很多的 Python 讲解教程和书籍&#xff0c;他们大都这样讲 Python 的&#xff1a;先从 Python 的发展历史开始&#xff0c;介绍 Python 的基本语法规则&#xff0c;Python 的 list, dict, tuple 等数据结构&#xff0c;然后再介绍字符串处理和正则表达式&#xff0…

win7操作系统在哪显示隐藏文件夹

win7操作系统在哪显示隐藏文件夹 打开计算机--组织--文件夹和搜索选项--查看--把 “隐藏受保护的操作系统文件”前面的钩去掉&#xff0c;选中“显示隐藏的文件、文件夹和驱动器”--确定

ASP.NET MVC4中调用WEB API的四个方法

当今的软件开发中&#xff0c;设计软件的服务并将其通过网络对外发布&#xff0c;让各种客户端去使用服务已经是十分普遍的做法。就.NET而言&#xff0c;目前提供了Remoting,WebService和WCF服务&#xff0c;这都能开发出功能十分强大的服务。然而&#xff0c;越来越多的互联网…

使用docker制作hexo镜像

个人博客&#xff1a;戳我&#xff0c;戳我 背景 这段时间一直在折腾我的博客&#xff0c;由于之前出现过一次电脑硬盘完全挂掉的情况&#xff0c;为了避免重新搭建博客系统&#xff0c;一直打算搞一个方便点的环境&#xff0c;能进行多机迁移之类的。正好&#xff0c;Docker完…

3D目标检测深度学习方法数据预处理综述

作者 | 蒋天元来源 | 3D视觉工坊&#xff08;ID: QYong_2014&#xff09;这一篇的内容主要要讲一点在深度学习的3D目标检测网络中&#xff0c;我们都采用了哪些数据预处理的方法&#xff0c;主要讲两个方面的知识&#xff0c;第一个是representation&#xff0c;第二个数据预处…

NTLM协议认证

第一篇blog&#xff0c;发现这是个记录学习过程的好地方。从基础的开始吧。 NTLM&#xff1a; 基本知识telnet的一种验证身份方式&#xff0c;即Windows NT LAN Manager (NTLM)&#xff1b; NTLM 是为没有加入到域中的计算机&#xff08;如独立服务器和工作组&#xff09;提供的…

新盒模型移动端的排版

这里采用的是新盒模型来进行排版&#xff1a; <div class"mytest">   <header></header>   <section></section>   <footer></footer> </div> 在CSS样式里添加如下样式 html,body{ height: 100%; } .mytest{ …

微信跳一跳高分辅助踩坑

旧博文&#xff0c;搬到 csdn 原文&#xff1a;http://rebootcat.com/2018/01/08/wechat_jump_hack/ 最近挺火的微信跳一跳 最近新版微信的『跳一跳』小程序着实火了一把&#xff0c;也把小程序这个概念再次推波助澜了一波&#xff0c;看来以后小程序这个入口会有大作为。 张小…

“编程能力差,90%的人会输在这点上!”谷歌开发:其实都是在瞎努力

这是一个很难让人心平气和的年代。疫情之下&#xff0c;很多人的都在面临着&#xff1a;失业、降薪、找不到工作、随时被裁等风险。但是&#xff1a;有心的人早已上路超车&#xff0c;做个人能力的升级——提高自己的不可替代性。李开复曾提出过“五秒钟准则”&#xff1a;一项…

64位win7安装IIS7时不能浏览asp的问题

64位win7高级家庭版安装IIS7&#xff0c;安装完成后只能浏览静态页&#xff0c;找了很多的教程都没有解决&#xff0c;最后在一个博客里看到说64位系统下ASP是不支持的ODB读取ACC的数据库的&#xff0c;因此需要开启32位应用程序的支持。 方法是&#xff1a; Internet 信息服务…

0525 项目回顾7.0

一、sprint总结 当谈到团队&#xff0c;我开始真的不知道团队是怎么样的&#xff0c;怎么样进行工作的&#xff0c;要该怎么出力团队的关系&#xff0c;有时候会涉及到个人问题&#xff0c;是不是该考虑进来&#xff0c;但是很多时候是不能的&#xff0c;每一个人作为团队的一份…

辩证看待 iostat

旧博文&#xff0c;搬到 csdn 原文&#xff1a;http://rebootcat.com/2018/01/16/using-iostat-dialectically/ 前言 经常做系统分析会接触到很多有用的工具&#xff0c;比如 iostat,它是用来分析磁盘性能、系统 I/O 的利器。 本文将重点介绍 iostat 命令的使用&#xff0c;并…

搞机器学习,Python和R哪个更合适?

【编者按】如果你正想构建一个机器学习项目&#xff0c;但却纠结于如何选择编程语言&#xff0c;这篇文章将是你所需要的。这篇文章不仅帮助你理解Python和R这两种语言的区别&#xff0c;还有助于你了解各个语言多方面的优势。作者 | Manav Jain译者 | Joe&#xff0c;编辑 | 夕…

Java安装方法

第1章 Java简介及开发环境搭建 实验1 JDK的下载、安装与配置 【实验目的】 &#xff08;1&#xff09;熟悉JDK工具包的下载及安装过程。 &#xff08;2&#xff09;掌握JAVA_HOME、CLASSPATH及Path的设置内容。 &#xff08;3&#xff09;掌握Java程序运行原理及Javac、Java命…

Hash函数的安全性

我们为了保证消息的完整性&#xff0c;引进了散列函数&#xff0c;那么散列函数会对安全正造成什么影响呢&#xff1f;这是需要好好研究一番的问题。 三个概念&#xff1a; 1.如果y<>x&#xff0c;且h&#xff08;x&#xff09;h&#xff08;y&#xff09;&#xff0c;则…

一键安装python3环境

旧博文&#xff0c;搬到 csdn 原文&#xff1a;http://rebootcat.com/2018/04/15/python3_in_a_box/ 一键安装python3环境 由于现在逐步转移到 python3 进行开发&#xff0c;但是很多机器并没有预装 python3 环境&#xff0c;所以需要安装。 所以分享一个我常用的&#xff0c…

认知智能再突破,阿里 18 篇论文入选 AI 顶会 KDD

作者 | 马超责编 | 屠敏头图 | CSDN 下载自东方 IC出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;近日&#xff0c;国际知识发现与数据挖掘协会KDD在官网(https://www.kdd.org/kdd2020)公布其2020年度的论文收录结果&#xff0c;笔者看到阿里共有18篇论文入选&…

python采集cpu信息

旧博文&#xff0c;搬到 csdn 原文&#xff1a;http://rebootcat.com/2018/05/20/analyze_cpu/ python脚本采集cpu 经常要做一些 linux 系统上的性能分析或者采集 cpu/mem/bandwidth 上报到监控系统。 分享一个我平常常用到的 cpu 采集脚本&#xff0c;原理是分析 /proc/stat…

Pretty Login便携版:Windows 7登录界面修改器

Pretty Login是由chnable开发的一个美化小工具&#xff0c;用来辅助修改Widnows 7登陆界面的背景图片&#xff0c;除此之外&#xff0c;它也能定制欢迎界面上的文本、按钮样式&#xff0c;如设置阴影、半透明效果。 由于Windows 7限制登录背景图片的大小不超过255KB&#xff0c…

来了来了!趋势预测算法大PK!

作者 | 王哲责编 | Carol头图 | CSDN 付费下载自视觉中国趋势预测在很多应用场景中都会起到至关重要的作用&#xff0c;比如淘宝商家会考虑库存量应该保持在多少才能够满足客户需求&#xff0c;商场希望得知假期会迎来多大的客流量以安排系列活动&#xff0c;机场想要预测五一黄…

hdu 5713(状态压缩DP)

要进行两次dp&#xff0c; 第一个&#xff0c;dp[i],1<i<(1<<n) 其中用i的二进制形式表示已选择的点。 dp[i] 用来保存i中的点构成一个连通块&#xff0c;边集多少种可能。 转移方程&#xff1a; save[0] 1;//这里用save[i]表示dp[i]for(int i1;i<(1<<n)…