排序算法之堆排序

一、什么是堆

  如果一个完全二叉树的每个节点,都不大于它的子节点,就可以称之为堆。所谓完全二叉树,就是除了叶子节点以外,所有的其他节点,都有完整的左字树和右子树,除了最后一层的非叶子节点以外。

                                                   

二、堆排序算法的大体脉络

        1、对无序的数据先建一个堆,

        2、输出堆顶元素,

        3、然后以最后一个元素代替堆顶元素,

        4、进行调整,使之仍然为一个堆。

        5、重复步骤2,3,4,直到堆中只剩下一个元素。

三、堆排序算法的详细过程

       1、填充

  首先,将这些无序的数字,填充成一个完全二叉树,但这时一般是不能够满足堆的要求的。没有关系,我们后面来进行调整。先来看看填充的过程。实际上,填充的顺序就是按照树的层次遍历的顺序,即从上到下,从左到右,一层一层往下放。就这样放完一层,放二层,放完二层,放三层,直到所有的数都放完为止。

                                                

  2、建堆

  填充完毕后,开始建堆的过程。显然,所有的叶子节点,都满足建堆的要求,因为它没有字节点。我们可以从最后一个非叶子节点开始。如图1所示,这里就是7,它满足堆的要求,再向前看5,这个节点不满足要求,右字树比它要小,需要把它和右子树互换一下,互换后如图2所示。再向前看2,它需要和做孩子互换,互换后,如图3所示。再向前看,现在到10,和之前的情况有些不同,10比之前的两个孩子都大,那到底该和哪一个孩子交换呢?稍微考虑一下,我们应该和最小的那个孩子交换,不然的话,我们交换完以后,仍然不能满足堆的要求。换过后,如图4所示。注意,10 换下来以后,破坏了原来满足要求的字树,所以还应该再调整,10和5应该互换,互换后,如图5所示。最后是6和1换,换后如图6所示。注意,6换下来以后,破坏了原来满足要求的字树,所以还应该再调整,6和2应该互换,互换后,如图7所示。至此,一个堆就建好了。这个堆满足的性质是,所以的父节点的值都不大于它的叶子节点的值。

             图1                                                                      图2                                                                                 图3

 

            图4                                                                         图5                                                                                   图6 

                 图7

   3、筛选并输出堆顶元素

  从初始的这个堆中,输出堆顶的这个元素。如图8所示,先输出1,然后根节点就空了。接着如图9,我们可以把最后一个元素9提拔上来,让9做根元素。显而易见,现在除了新提拔的这个根节点以外,其他的节点都满足堆的性质,那么就需要调整这个根节点。9要和左右孩子相比,与较小的孩子2互换。换后如图10所示。接着对局部的数,我们再调整,直到9落地为止,换后如图11。至此,这个完全二叉树就满足堆的要求了,我们输出2,如图12。然后,如图13,把最后一个元素10提拔上去,然后,还像之前一样,把10逐步向下调整,这个完全二叉树满足堆的要求后,输出堆顶的元素3,如图14。在堆排序的术语上,我们把较大的元素从顶层落到底层的过程称为“筛选”。然后再把最后一个元素提拔上去,在筛选,再提拔,再筛选,重复这个过程,堆变得越来越小,直至整个堆只剩下一个元素,把这个元素也输出,我们的堆排序过程也就结束了。

                        图8                                                                         图9                                                                 图10

 

                      图11                                                        图12                                                                                     图13

 

                  图14                                                                                      图15

四、代码实现

  堆排序可以用二叉树的结构来表示,但在 实际应用中,我们还可以更节省内存空间,用一位数组来表示这个二叉树,当数据量很大的时候,一维数组占用的内存比二叉树占用的内存小很多。当然,对于一般的二叉树,我们是不能这样表示的,现在的完全二叉树具有特殊性,我们可以用一维数组来表示它。

       从面向对象的角度出发,对二叉树,这要能给点一个节点,确定父节点和子节点在哪里就可以了,至于在内存中怎么存储的,并不重要。如下图所示,对于完全二叉树,给定当前节点,其父子点和子节点都是可以唯一确定的。把这些节点序号,对应到一维数组元素的下标,就可以用一维数组来表示完全二叉树了。

                                          

  因为我们用一维数组来代替完全二叉树,所以填充的过程就免去了,可以直接进行筛选,然后提拔最后一个元素,再筛选,直至堆中只剩下最后一个元素,输出,堆排序完成。代码如下:

public class HeapSort {public static void main(String[] args) {int[] a={7,2,3,6,8,5};heapSort(a);}public static void heapSort(int[] a){//建立初始堆for(int i=(a.length-1)/2;i>=0;i--) heapOne(a,a.length,i);//边输出堆顶,边调整int n=a.length; //剩余元素数while (n>0){System.out.print(a[0]+" ");//输出堆顶元素a[0]=a[n-1];//最后一个元素移动到堆顶n--;//要排序的数组的长度减1heapOne(a,n,0);}System.out.println();}//节点K进行筛选//a:堆数据 , n:堆中有效数据的个数 ,K:待筛选的节点public static void heapOne(int[] a,int n,int k){int k1=2*k+1; //K节点的左子节点int k2=2*k+2; //K节点的右子节点if(k1>=n && k2>=n)  return;//已经是叶子了int a1=Integer.MAX_VALUE;int a2=Integer.MAX_VALUE;if(k1<n) a1=a[k1]; //左孩子值if(k2<n) a2=a[k2]; //右孩子值if(a[k]<=a1&&a[k]<=a2) return;//已经符合堆的要求了//找到左右孩子中最小的,和它交换if(a1<a2){int t=a[k];a[k]=a[k1];a[k1]=t;heapOne(a,n,k1);//继续筛选子树}else {int t=a[k];a[k]=a[k2];a[k2]=t;heapOne(a,n,k2);//继续筛选子树
        }}
}
View Code

 ------------------------------------------------------------------------------------------------------------------------------------------------

参考链接:

http://www.iqiyi.com/v_19rrhzzs1k.html

转载于:https://www.cnblogs.com/hezhiyao/p/7552566.html

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

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

相关文章

Codeforces Round #434 (Div. 2)【A、B、C、D】

Codeforces Round #434 (Div. 2) codeforces 858A. k-rounding【水】 题意&#xff1a;已知n和k&#xff0c;求n的最小倍数x&#xff0c;要求x后缀至少有k个0。 题解&#xff1a;答案就是10^k和n的最小公倍数。 1 #include<cstdio>2 #include<cstring>3 #include&l…

PLC与触摸屏练习

电机正反转 触摸屏 要用触摸屏进行仿真是不要忘了先启动梯形图测试 效果 1-2例 行程开关控制的自动循环 梯形图 触摸屏 下面只是用了四个开关&#xff0c;可以根据自己想要实现的按照梯形图添加 题目 梯形图 电动机星三角减压启动控制 题目及要求 触摸屏截图 运算 把显示的数值…

Django里面是文件静态化的方法

看Django官网的时候&#xff0c;由于自己的英语基础较差&#xff0c;而实现的谷歌翻译比较烂&#xff0c;只能看懂个大概。在文件静态化的时候&#xff0c;讲的比较繁琐一点&#xff0c;没怎么看懂&#xff0c;遂询问了一下其他人&#xff0c;明白了许多&#xff0c;但是细节需…

RabbitMQ 声明Queue时的参数们的Power

RabbitMQ 声明Queue时的参数们的Power 参数们的Power 在声明队列的时候会有很多的参数 public static QueueDeclareOk QueueDeclare(this IModel model, string queue "", bool durable false, bool exclusive true, bool autoDelete true, IDictionary<strin…

解决Firefox已阻止运行早期版本Adobe Flash

解决Firefox已阻止运行早期版本Adobe Flash 类别 [随笔分类]web 解决Firefox已阻止运行早期版本Adobe Flash 最近火狐浏览器不知抽什么风&#xff0c;每次打开总提示"Firefox已阻止(null)运行早期版本的Adobe Flash"。要命的是它提示的解决办法根本不管用&#xf…

使用MyBatista----上传图像

使用MyBatis上传图像&#xff0c;使用的是Oracle的数据库表&#xff0c;有一个TEACHER表&#xff0c;有7列&#xff0c;有1列是存储图片的&#xff0c;类型用BLOB&#xff0c;最大容量是4G&#xff0c;以二进制的形式写入数据库表。 建立这个表的对应实体类Teacher&#xff0c;…

BZOJ 2768 [JLOI2010]冠军调查

还说还剩十分钟A一道水题&#xff0c;然后发现和善意的投票一模一样粘个代码过去直接A。。。 装作自己又写了一道题。 题面 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<…

【OpenCV函数】轮廓提取;轮廓绘制;轮廓面积;外接矩形

FindContours 在二值图像中寻找轮廓 int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour, int header_sizesizeof(CvContour), int modeCV_RETR_LIST, int methodCV_CHAIN_APPROX_SIMPLE, CvPoint offsetcvPoint(0,0) ); image 输入的 8-比…

Windows下编译TensorFlow1.3 C++ library及创建一个简单的TensorFlow C++程序

由于最近比较忙&#xff0c;一直到假期才有空&#xff0c;因此将自己学到的知识进行分享。如果有不对的地方&#xff0c;请指出&#xff0c;谢谢&#xff01;目前深度学习越来越火&#xff0c;学习、使用tensorflow的相关工作者也越来越多。最近在研究tensorflow线下采用 pytho…

粉红小猪中有一个叫“快乐小鸡”的游戏

最近在学习svg,书看了一本 然后再找了个框架 snap.svg 摸索着写了个游戏给女儿玩。哈哈。即涨知识又娱乐。 转载于:https://www.cnblogs.com/goldli/p/7649898.html

idea .defaultMessage

idea .defaultMessage 等同于eclipse里的getDefaultMessage idea只能能获取到bean设置NotBlank等message响应到jsp的key&#xff0c;不能在jsp里获取validationMessage properties文件里的value 那么我们就不要value只要key 转载于:https://www.cnblogs.com/duneF/p/7654780.h…

【vue系列之二】详解vue-cli 2.0配置文件

上次给大家分享的是用vue-cli快速搭建vue项目&#xff0c;虽然很省时间和精力&#xff0c;但想要真正搞明白&#xff0c;我们还需要对其原理一探究竟。 大家拿到一个项目&#xff0c;要快速上手&#xff0c;正确的思路是这样的&#xff1a; 首先&#xff0c;如果在项目有readme…

4. Spring 如何通过 XML 文件配置Bean,以及如何获取Bean

在 Spring 容器内拼凑 bean 叫做装配。装配 bean 的时候&#xff0c;你是在告诉容器&#xff0c;需要哪些 bean &#xff0c;以及容器如何使用依赖注入将它们配合在一起。 理论上&#xff0c;bean 装配的信息可以从任何资源获得&#xff0c;包括属性文件&#xff0c;关系数据库…

基于用户击键特征的身份鉴别系统

简单来说&#xff0c;我们要做的就是一种通过用户敲击键盘的习惯进行身份鉴别的系统。国内外之前有一些相关研究&#xff0c;但是通常是数千条数据训练&#xff0c;而且不能随意改变敲击的字符串&#xff0c;或者是有的要求采用带有压力传感器的键盘&#xff0c;难以实用和推广…

常见三种字符编码的区别:ASCII、Unicode、UTF-8

什么是字符编码&#xff1f; 计算机只能处理数字&#xff0c;如果要处理文本&#xff0c;就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特&#xff08;bit&#xff09;作为一个字节&#xff08;byte&#xff09;&#xff0c;所以&#xff0c;一个字节能表…

导航,头部,CSS基础

制作自己的导航条。HTML头部元素&#xff1a;<base> 定义了页面链接标签的默认链接地址<style> 定义了HTML文档的样式文件<link> 定义了一个文档和外部资源之间的关系练习样式表&#xff1a;行内样式表内嵌样式表外部样式表分别练习定义三类选择器&#x…

十五、导航,头部,CSS基础

制作自己的导航条。HTML头部元素&#xff1a;<base> 定义了页面链接标签的默认链接地址<style> 定义了HTML文档的样式文件<link> 定义了一个文档和外部资源之间的关系 练习样式表&#xff1a;行内样式表内嵌样式表外部样式表分别练习定义三类选择器&#…

【网络爬虫入门04】彻底掌握BeautifulSoup的CSS选择器

【网络爬虫入门04】彻底掌握BeautifulSoup的CSS选择器 广东职业技术学院 欧浩源 2017-10-21 1、引言 目前&#xff0c;除了官方文档之外&#xff0c;市面上及网络详细介绍BeautifulSoup使用的技术书籍和博客软文并不多&#xff0c;而在这仅有的资料中介绍CSS选择器的少之又少。…

Mybatis基于XML配置SQL映射器(一)

Durid和Mybatis开发环境搭建 SpringBoot搭建基于SpringSpringMvcMybatis的REST服务&#xff08;http://www.cnblogs.com/nbfujx/p/7694768.html&#xff09; Mybatis之代码生成器 Maven Plugin管理 1 <build>2 <plugins>3 <plugin>4 …

linux运维、架构之路-Zabbix监控

一、监控常用命令 1、物理服务器监控命令 ①添加yum源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo ②安装 yum -y install OpenIPMI ipmitoo…