原创不易,如果你觉得对你有用,哪怕一点点也好,请留下一个赞再走,谢谢啦啦啦!!

文章目录

  • 一、前期知识储备
    • 二、堆如何跟排序挂上钩的?
      • 三、堆排序思想
      • 四、如何进行堆排序(附亲手画的图)
        • 五、撸代码(详细注释,不怕你看不懂)
          • 六、 八千万数据测试堆排序性能
          • 七、分享交流

一、前期知识储备

  1. 堆排序是对于完全二叉树而言

完全二叉树的那些事:

  1. 定义:对于一个树高为h的二叉树,如果其第0层至第h-1层的节点都满。如果最下面一层节点不满,则所有的节点在左边的连续排列,空位都在右边。这样的二叉树就是一棵完全二叉树(不理解没关系,是我的错,不许喷我
  2. 性质:如果n个节点的完全二叉树的节点按照层次并按从左到右的顺序从0开始编号,对于每个节点都有:
    • 序号为0的节点是根对于i>0,
    • 其父节点的编号为(i-1)/2。
    • 若2·i+1<n,其左子节点的序号为2·i+1,否则没有左子节点
    • 若2·i+2<n,其右子节点的序号为2·i+2,否则没有右子节点。

是不是很枯燥?是不是看不下去?小伙子,别着急,磨刀不误砍柴工。,我给你上个图,你就懂上面所说的一切了。

2. 那堆又是什么呢?

  • 堆的定义:
  • 每个非叶子结点的值都大于或等于其左孩子和右孩子结点的值,称之为大根堆
  • 每个结点的值都小于或等于其左孩子和右孩子结点的值,称之为小根堆
  • 大根堆常用于升序操作
  • 小根堆常用于降序操作

千言万语不胜一图,看图哈

二、堆如何跟排序挂上钩的?

理由很简单,因为堆这种数据结构可以用于排序(虽然感觉是废话,哈哈哈哈,不管了,先说人话)不信你往下看。

  • 根据大顶堆的特性,我们可以知道大根堆的根节点就是所有节点的最大值
  • 所以我们可以将最大值的根节点取下(人话:替换)与最后一个节点的值进行互换,然后将剩余的节点继续构造成大根堆

三、堆排序思想

非常重要呀呀呀,不懂也没关系,下面有图有真相

  1. 首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端(根节点)

  2. 将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1

  3. 将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

四、如何进行堆排序(附亲手画的图)

上面说的是不是还是很懵逼???,没关系,既然是说人话,那我就上个图来解释:

说明:以下画的树必须满足完全二叉树,因为这是堆这个数据结构的前提

  1. 给定一个数组,如何知道非哪些元素是非叶子节点个数呢?
  • 根据一条公式即可知道了,total = arry.length-1(下标从0开始)
  • 看下图哈
  1. 构建大顶堆顺序
  • 依次处理非叶子节点
  • 顺序是从上往下、从右往左

  1. 堆排序


简要说一下人话:

  1. 给定一个待排序的数组,我们要将它变成大顶堆数组,这里之所以要给出完全二叉树来,是因为这样便于理解哈
  2. 我们是直接操作数组使其变成大顶堆,而不是树,但是原理是一样的,因为我们操作数组的时候就是用到上面说的完全二叉树的性质(下标索引找孩子节点)
  3. 这里用树来演示,就是为了便于理解,真正操作是对数组直接操作。

再放两个图:
仔细品,不懂可以留言交流呀!图丑也欢迎留言喷哈哈哈

调整好大顶堆后,根(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千万的数据进行堆排序,我的电脑用时:

  1. 可能我的电脑配置比较差劲,但是比冒泡、简单排序好太多了,不信你自己玩玩,我这破电脑就不试了哈
  2. 欢迎留言看看你的运行时间是多少,看是不是吊打我电脑呢,哈哈哈哈哈
  3. 看在我熬夜肝图的份上就点个赞吧,图不好也可以喷哈哈哈

都已经看到这了,再不给赞,那就说不过去了吧

七、分享交流

最后有兴趣一起交流的,可以关注我的公众号:这里你能够学到很实用的技巧,不是常用的我不说,公众号回复提取码即可获取以下学习资料啦啦啦啦,喜欢就拿去吧!!

(链接时常会失效,若出现此类情况,可以加我微信:17722328325(加时请备注:学习资料))

  1. Java web从入门到精通电子书

  2. Python机器学习电子书

  3. Python400集(北京尚学堂)

  4. JavaScript项目案例、经典面试题

  5. Java300集(入门、精通)

  6. Java后端培训机构录集(同事培训内部提供)

  7. java重要知识pdf文档(价值连城呀呀,不收藏你会后悔的)

额外一堆电子书:



        喜欢就关注吧,点个赞吧



这是分享生活、电影、资料、书籍的一个公众号,有需要的也可以看看哟!


放牛娃谈堆排序---(为了说明白,我重新学习了如何说“人话”)相关推荐

  1. 大众点评网谈成功秘诀:明白用户感兴趣、需要和寻找的是什么

    如今的互联网用户,大多都能够熟练地使用搜索引擎查找到自己需要的信息,"浏览.输入.搜索"早已成为最普遍的上网场景.但是,并不是所有的互联网企业都懂得怎样通过掌握"场景&q ...

  2. 浅谈bootloader【谈的很清晰明白】

    文章目录 什么是Bootloader ECU的Bootloader Bootloader框架 ECU Bootloader原理 1.预编程阶段 2.编程阶段 3.编程结束 总体流程 Bootloade ...

  3. Himi浅谈4年游戏开发de自学历程!(牛人是如何学习的)

    http://www.himigame.com/himistudy/382.html 上班之前: 学习J2me的时候,每天除了饿了去吃饭之外,全部用来学习,基本上是3天里有一天通宵: 写了四款基于Kj ...

  4. 堆排序怎么建立初始堆_学习笔记-详解堆排序

    本文目的 上一章节已经详细的向大家介绍过排序的相关概念(详见学习笔记-排序简单介绍) ,本文旨在为大家详细的介绍堆排序. 堆排序 堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序 ...

  5. Peter Cnudde谈雅虎如何使用Hadoop、深度学习和大数据平台

    \ 本文要点 \ 了解雅虎如何利用Hadoop和大数据平台技术: \ 在类似Flickr和Esports这样的产品中,雅虎如何使用深度学习技术进行场景检测和对象识别: \ 机器学习在图像识别.定向广告 ...

  6. 浅谈三个星期零基础入门学习Thinkphp5开发restful-api接口的心得和总结

    一丢丢心得体会: 首先不得不说一下,学习一门知识,真的就像建一栋高楼一样,地基必须的稳固,否则你辛辛苦苦建的楼可能随时会垮掉,这一点在我学习thinkphp5的路上深有体会,同时了自此我也爱上了写博客 ...

  7. 浅谈JavaScript作用域,关于Java的学习路线资料

    javascript是目前web领域中使用非常广泛的语言,不管是在前端还是在后端都能看到它的影子,可以说web从业者不论怎样都绕不开它.在前端领域,各种框架层出不穷.在后端领域,nodejs可谓如火如 ...

  8. 打脸往事!罗振宇2015年谈乐视、暴风 一口毒奶“奶死”不少人?

    要说人生尴尬的时刻是绝对没有之最,当一件尴尬往事再被翻起的时候,尴尬的程度都会加倍.公众人物的一些往事被翻出来的时候,打脸尴尬程度就堪称公开处刑. 最近暴风集团实控人冯鑫因涉嫌犯罪,被公安机关采取强制 ...

  9. 刘强东再谈无界零售:场景无限、货物无边、人企无间

    来源丨财新杂志(ID:i-caijing) 在<第四次零售革命>中,我曾经分享过我对零售未来的判断:在下一个10年到20年,零售业将迎来第四次零售革命. 同历史上的三次革命(百货商店.连锁 ...

  10. 由谈退格键的实现来学习字符编码

    我曾以为老师的话是真的,我曾以为老师会为自己说出的话负责,但事实证明很多时候是照本宣科. 这次在公司做Fcitx输入法时,想到退格删除的字节数的不同,即退格键一按到底删除的是一个字节还是两个字节或者多 ...

最新文章

  1. Windows 10 系统版本更新历史
  2. mysql存储过程打不开了_请问mysql存储过程的问题,我找了几个例子一个都运行不起来,...
  3. spring-boot-starter-logging
  4. 7天下载破千万,让你“变老”的FaceApp如何爆发式增长?
  5. 用友NC单据模板公式
  6. 安装python解释器的时候遇到user installations are disabled via policy on the machine”
  7. 响铃:社交型流量平台,为何线上平台都扎堆去线下造节
  8. 清理XCode缓存文件
  9. 计算机图形学直线算法程序,计算机图形学直线生成算法实现.doc
  10. python写入excel文件追加写入_Python读写/追加excel文件Demo
  11. HTML5 canvas 之 clip
  12. 【Windows】能上QQ却打不开网页(提示未连接到互联网,代理服务器出现问题,或者地址有误。)的解决办法
  13. css实现仿element ui配色的小圆圈状态标记
  14. 同步发电机转子的转动惯量与运动方程(二) 同步发电机的转子运动方程
  15. Flink内存管理源码解读之基础数据结构
  16. Linux系统(Ubuntu)编写C语言程序
  17. 我接的是地啊,不,你接的是土!
  18. stm32F767开发版基本介绍
  19. synchronized关键字
  20. Ultraedit使用小技巧

热门文章

  1. java实现数字0-9转换为繁体字
  2. 搜索百度网盘资源网站地址
  3. ubuntu19.04下VirtualBox与虚拟机win7共享文件夹
  4. 从看脸到读心:深度理解人的视觉技术走到哪了?
  5. 帝国cms 图集模型 php,帝国CMS教程图集字段的大图,小图,说明的调用
  6. 计算机组装中如何看硬件型号,如何查看主板型号?(三种方法!)
  7. 微分方程(Differential Equation)
  8. java 替换 ppt内容_Java 替换PPT文档中的文本和图片
  9. 惊鸿一现的永恒经典2007-05-07 09:40:18
  10. 云计算时代迎接挑战方能脱颖而出