放牛娃谈堆排序---(为了说明白,我重新学习了如何说“人话”)
原创不易,如果你觉得对你有用,哪怕一点点也好,请留下一个赞再走,谢谢啦啦啦!!
文章目录
- 一、前期知识储备
- 二、堆如何跟排序挂上钩的?
- 三、堆排序思想
- 四、如何进行堆排序(附亲手画的图)
- 五、撸代码(详细注释,不怕你看不懂)
- 六、 八千万数据测试堆排序性能
- 七、分享交流
一、前期知识储备
- 堆排序是对于完全二叉树而言
完全二叉树的那些事:
- 定义:对于一个树高为h的二叉树,如果其第0层至第h-1层的节点都满。如果最下面一层节点不满,则所有的节点在左边的连续排列,空位都在右边。这样的二叉树就是一棵完全二叉树(不理解没关系,是我的错,不许喷我)
- 性质:如果n个节点的完全二叉树的节点按照层次并按从左到右的顺序从0开始编号,对于每个节点都有:
- 序号为0的节点是根对于i>0,
- 其父节点的编号为(i-1)/2。
- 若2·i+1<n,其左子节点的序号为2·i+1,否则没有左子节点
- 若2·i+2<n,其右子节点的序号为2·i+2,否则没有右子节点。
是不是很枯燥?是不是看不下去?小伙子,别着急,磨刀不误砍柴工。,我给你上个图,你就懂上面所说的一切了。
2. 那堆又是什么呢?
- 堆的定义:
- 每个非叶子结点的值都大于或等于其左孩子和右孩子结点的值,称之为大根堆
- 每个结点的值都小于或等于其左孩子和右孩子结点的值,称之为小根堆
- 大根堆常用于升序操作
- 小根堆常用于降序操作
千言万语不胜一图,看图哈
二、堆如何跟排序挂上钩的?
理由很简单,因为堆这种数据结构可以用于排序(虽然感觉是废话,哈哈哈哈,不管了,先说人话)不信你往下看。
- 根据大顶堆的特性,我们可以知道大根堆的根节点就是所有节点的最大值
- 所以我们可以将最大值的根节点取下(人话:替换)与最后一个节点的值进行互换,然后将剩余的节点继续构造成大根堆
三、堆排序思想
非常重要呀呀呀,不懂也没关系,下面有图有真相
首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端(根节点)
将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
四、如何进行堆排序(附亲手画的图)
上面说的是不是还是很懵逼???,没关系,既然是说人话,那我就上个图来解释:
说明:以下画的树必须满足完全二叉树,因为这是堆这个数据结构的前提
- 给定一个数组,如何知道非哪些元素是非叶子节点个数呢?
- 根据一条公式即可知道了,
total = arry.length-1
(下标从0开始)- 看下图哈
- 构建大顶堆顺序
- 依次处理非叶子节点
- 顺序是从上往下、从右往左
- 堆排序
简要说一下人话:
- 给定一个待排序的数组,我们要将它变成大顶堆数组,这里之所以要给出完全二叉树来,是因为这样便于理解哈
- 我们是直接操作数组使其变成大顶堆,而不是树,但是原理是一样的,因为我们操作数组的时候就是用到上面说的完全二叉树的性质(下标索引找孩子节点)
- 这里用树来演示,就是为了便于理解,真正操作是对数组直接操作。
再放两个图:
仔细品,不懂可以留言交流呀!图丑也欢迎留言喷哈哈哈
调整好大顶堆后,根(arry[0])节点值跟倒二节点(arry[5])值又互换,看图
五、撸代码(详细注释,不怕你看不懂)
纸上得来终且浅,得知此时要躬行,看了再多还是得撸代码
如果你看到这里了,要个赞不过分吧,哈哈哈哈
代码:
package suanFa;import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;/*** 堆排序的学习:* 时间复杂度:O(nlogn),远比冒泡,简单选择,直接插入的O(n^2)好很多,但是它是个不稳定的算法* @公众号 放牛娃学编程**/public class HeapSort {public static void main(String[] args) {// int[] arry = {20};
// //测试一波
// Heapsort(arry);
// System.out.println("数组已经排序完了:"+Arrays.toString(arry));//性能测试一波,8千万数据排序int[] arry = new int[80000000];for(int i = 0; i < 80000000; i++){arry[i] = (int) (Math.random()*80000000);}Date start = new Date();Heapsort(arry);Date end = new Date();SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String startTime = simpleDateFormat.format(start);String endTime = simpleDateFormat.format(end);System.out.println("排序前的时间:"+startTime);System.out.println("排序后的时间:"+endTime);}//构建大顶堆public static void Heapsort(int[] arry){//构建一棵大顶堆,策略:依次处理非叶子节点,从右往左,从上往下for(int i = arry.length / 2 - 1; i >= 0; i--){HeapAdjust(arry, i, arry.length);}//开始排序(取大顶堆的根节点,即使最大值,跟数组最后一个调换位置,然后将剩余的数重新调整为大顶堆)for(int j = arry.length - 1; j > 0 ; j--){//交换位置swap(arry,0, j);//将剩余的节点(这里是数组)调整为大顶堆HeapAdjust(arry, 0, j);}}private static void swap(int[] arry, int i, int j) {// TODO Auto-generated method stubint temp = arry[i];arry[i] = arry[j];arry[j] = temp;}//调整堆/*** * @param arry 需要调整的数组* @param index 非叶子节点下标索引* @param length 需要调整的数组长度*/public static void HeapAdjust(int[] arry, int index, int length){//1.0 用一个临时变量将该节点值暂时保存起来int temp = arry[index];int k;//下标为什么要这样变化,根据完全二叉树的父节点与子节点的关系得出来的(编号从0开始编号)for(k=2*index + 1; k < length; k = 2*k+1){if(k+1 < length && arry[k] < arry[k+1]){//指向右子节点(较大的下标)++k;}/**如果父节点已经是大于等于孩子节点(那直接退出循环,为什么可以这样呢?因为我们采取的策略是:处理非叶子节点时,从右往左,从上往下。假设非叶子节点编号为:4,3,2,1)**/if(temp >= arry[k]){break;}//替换arry[index] = arry[k];index = k;}//插入arry[index] = temp;}
}
六、 八千万数据测试堆排序性能
上图程序中,我用8千万的数据进行堆排序,我的电脑用时:
- 可能我的电脑配置比较差劲,但是比冒泡、简单排序好太多了,不信你自己玩玩,我这破电脑就不试了哈
- 欢迎留言看看你的运行时间是多少,看是不是吊打我电脑呢,哈哈哈哈哈
- 看在我熬夜肝图的份上就点个赞吧,图不好也可以喷哈哈哈
都已经看到这了,再不给赞,那就说不过去了吧
七、分享交流
最后有兴趣一起交流的,可以关注我的公众号:这里你能够学到很实用的技巧,不是常用的我不说,公众号回复提取码即可获取以下学习资料啦啦啦啦,喜欢就拿去吧!!
(链接时常会失效,若出现此类情况,可以加我微信:17722328325(加时请备注:学习资料))
Java web从入门到精通电子书
Python机器学习电子书
Python400集(北京尚学堂)
JavaScript项目案例、经典面试题
Java300集(入门、精通)
Java后端培训机构录集(同事培训内部提供)
java重要知识pdf文档(价值连城呀呀,不收藏你会后悔的)
额外一堆电子书:
喜欢就关注吧,点个赞吧
这是分享生活、电影、资料、书籍的一个公众号,有需要的也可以看看哟!
放牛娃谈堆排序---(为了说明白,我重新学习了如何说“人话”)相关推荐
- 大众点评网谈成功秘诀:明白用户感兴趣、需要和寻找的是什么
如今的互联网用户,大多都能够熟练地使用搜索引擎查找到自己需要的信息,"浏览.输入.搜索"早已成为最普遍的上网场景.但是,并不是所有的互联网企业都懂得怎样通过掌握"场景&q ...
- 浅谈bootloader【谈的很清晰明白】
文章目录 什么是Bootloader ECU的Bootloader Bootloader框架 ECU Bootloader原理 1.预编程阶段 2.编程阶段 3.编程结束 总体流程 Bootloade ...
- Himi浅谈4年游戏开发de自学历程!(牛人是如何学习的)
http://www.himigame.com/himistudy/382.html 上班之前: 学习J2me的时候,每天除了饿了去吃饭之外,全部用来学习,基本上是3天里有一天通宵: 写了四款基于Kj ...
- 堆排序怎么建立初始堆_学习笔记-详解堆排序
本文目的 上一章节已经详细的向大家介绍过排序的相关概念(详见学习笔记-排序简单介绍) ,本文旨在为大家详细的介绍堆排序. 堆排序 堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序 ...
- Peter Cnudde谈雅虎如何使用Hadoop、深度学习和大数据平台
\ 本文要点 \ 了解雅虎如何利用Hadoop和大数据平台技术: \ 在类似Flickr和Esports这样的产品中,雅虎如何使用深度学习技术进行场景检测和对象识别: \ 机器学习在图像识别.定向广告 ...
- 浅谈三个星期零基础入门学习Thinkphp5开发restful-api接口的心得和总结
一丢丢心得体会: 首先不得不说一下,学习一门知识,真的就像建一栋高楼一样,地基必须的稳固,否则你辛辛苦苦建的楼可能随时会垮掉,这一点在我学习thinkphp5的路上深有体会,同时了自此我也爱上了写博客 ...
- 浅谈JavaScript作用域,关于Java的学习路线资料
javascript是目前web领域中使用非常广泛的语言,不管是在前端还是在后端都能看到它的影子,可以说web从业者不论怎样都绕不开它.在前端领域,各种框架层出不穷.在后端领域,nodejs可谓如火如 ...
- 打脸往事!罗振宇2015年谈乐视、暴风 一口毒奶“奶死”不少人?
要说人生尴尬的时刻是绝对没有之最,当一件尴尬往事再被翻起的时候,尴尬的程度都会加倍.公众人物的一些往事被翻出来的时候,打脸尴尬程度就堪称公开处刑. 最近暴风集团实控人冯鑫因涉嫌犯罪,被公安机关采取强制 ...
- 刘强东再谈无界零售:场景无限、货物无边、人企无间
来源丨财新杂志(ID:i-caijing) 在<第四次零售革命>中,我曾经分享过我对零售未来的判断:在下一个10年到20年,零售业将迎来第四次零售革命. 同历史上的三次革命(百货商店.连锁 ...
- 由谈退格键的实现来学习字符编码
我曾以为老师的话是真的,我曾以为老师会为自己说出的话负责,但事实证明很多时候是照本宣科. 这次在公司做Fcitx输入法时,想到退格删除的字节数的不同,即退格键一按到底删除的是一个字节还是两个字节或者多 ...
最新文章
- Windows 10 系统版本更新历史
- mysql存储过程打不开了_请问mysql存储过程的问题,我找了几个例子一个都运行不起来,...
- spring-boot-starter-logging
- 7天下载破千万,让你“变老”的FaceApp如何爆发式增长?
- 用友NC单据模板公式
- 安装python解释器的时候遇到user installations are disabled via policy on the machine”
- 响铃:社交型流量平台,为何线上平台都扎堆去线下造节
- 清理XCode缓存文件
- 计算机图形学直线算法程序,计算机图形学直线生成算法实现.doc
- python写入excel文件追加写入_Python读写/追加excel文件Demo
- HTML5 canvas 之 clip
- 【Windows】能上QQ却打不开网页(提示未连接到互联网,代理服务器出现问题,或者地址有误。)的解决办法
- css实现仿element ui配色的小圆圈状态标记
- 同步发电机转子的转动惯量与运动方程(二) 同步发电机的转子运动方程
- Flink内存管理源码解读之基础数据结构
- Linux系统(Ubuntu)编写C语言程序
- 我接的是地啊,不,你接的是土!
- stm32F767开发版基本介绍
- synchronized关键字
- Ultraedit使用小技巧
热门文章
- java实现数字0-9转换为繁体字
- 搜索百度网盘资源网站地址
- ubuntu19.04下VirtualBox与虚拟机win7共享文件夹
- 从看脸到读心:深度理解人的视觉技术走到哪了?
- 帝国cms 图集模型 php,帝国CMS教程图集字段的大图,小图,说明的调用
- 计算机组装中如何看硬件型号,如何查看主板型号?(三种方法!)
- 微分方程(Differential Equation)
- java 替换 ppt内容_Java 替换PPT文档中的文本和图片
- 惊鸿一现的永恒经典2007-05-07 09:40:18
- 云计算时代迎接挑战方能脱颖而出