堆是一种特殊的完全二叉树,其特点是所有父节点都比子节点要小,或者所有父节点都比字节点要大。前一种称为最小堆,后一种称为最大堆。

比如下面这两个:

那么这个特性有什么作用?既然题目是堆排序,那么肯定能用来排序。想要用堆排序首先要创建一个堆,如果对4 3 6 2 7 1 5这七个数字做从小到大排序,需要用这七个数创建一个最大堆,来看代码:

  1. public class HeapSort {
  2. private int[] numbers;
  3. private int length;
  4. public HeapSort(int[] numbers) {
  5. this.numbers = numbers;
  6. this.length = numbers.length;
  7. }
  8. /**
  9. * 调整二叉树
  10. * 如果父节点编号为x, 那么左子节点的编号是2x, 右子节点的编号是2x+1
  11. * 节点编号从1开始, 对应数组中的索引是编号-1
  12. * @param nodeId 节点编号, 从1开始
  13. */
  14. public void adjust(int nodeId) {
  15. int swapId;
  16. int flag = 0; //是否需要继续向下调整
  17. while(nodeId * 2 <= this.length && flag == 0) {
  18. //首先判断它和左子节点的关系, 并用swapId记录值较小的节点编号(最大堆是记录较大的)
  19. int index = nodeId - 1; //节点对应数组中数字的索引
  20. int leftChild = nodeId * 2 - 1; //左子节点对应数组中数字的索引
  21. int rightChild = nodeId * 2; //右子节点对应数组中数字的索引
  22. if(numbers[index] < numbers[leftChild])  {
  23. swapId = nodeId * 2;
  24. } else {
  25. swapId = nodeId;
  26. }
  27. //如果有右子节点, 再与右子节点比较
  28. if(nodeId * 2 + 1 <= this.length) {
  29. if(numbers[swapId - 1] < numbers[rightChild])
  30. swapId = nodeId * 2 + 1;
  31. }
  32. //如果最小的节点编号不是自己, 说明子节点中有比父节点更小的
  33. if(swapId != nodeId) {
  34. swap(swapId, nodeId);
  35. nodeId = swapId;
  36. } else {
  37. flag = 1;
  38. }
  39. }
  40. }
  41. /**
  42. * 交换两个节点的值
  43. * @param nodeId1
  44. * @param nodeId2
  45. */
  46. public void swap(int nodeId1, int nodeId2) {
  47. int t = numbers[nodeId1 - 1];
  48. numbers[nodeId1 - 1] = numbers[nodeId2 - 1];
  49. numbers[nodeId2 - 1] = t;
  50. }
  51. /**
  52. * 创建最大堆
  53. */
  54. public void createMaxHeap() {
  55. //从最后一个非叶节点到第一个节点依次向上调整
  56. for(int i = this.length / 2; i >= 1; i--) {
  57. adjust(i);
  58. }
  59. }
  60. public static void main(String[] args) {
  61. int[] numbers = new int[] { 4, 3, 6, 2, 7, 1, 5 };
  62. for(int x = 0; x < numbers.length; x++) {
  63. System.out.print(numbers[x] + "  ");
  64. }
  65. System.out.println();
  66. HeapSort heap = new HeapSort(numbers);
  67. heap.createMaxHeap();
  68. }
  69. }

对本例中的数列,从this.length / 2到1,共执行了三轮循环。

第一轮:

第二轮:


第三轮:

调整完成后,当前的二叉树已经符合最大堆的特性,可以用来从小到大排序。堆排序的原理是,交换堆顶和最后一个节点的数字,即把最大的数字放到数组最后,然后对除了最大数的前n-1个数从新执行调整过程,使其符合最大堆特性。重复以上过程直到堆中只剩下一个数字。

  1. public void sort() {
  2. while(this.length > 1) {
  3. swap(1, this.length);
  4. this.length--;
  5. adjust(1);
  6. }
  7. for(int x = 0; x < numbers.length; x++) {
  8. System.out.print(numbers[x] + "  ");
  9. }
  10. }

堆排序的时间复杂度和快速排序的平均时间复杂度一样,是O(nlogn)。

Java与算法之(8) - 堆排序的更多相关文章

  1. java排序算法(三):堆排序

    java排序算法(三)堆排序 堆积排序(HeapSort)是指利用堆积树这种结构所设计的排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法.辅助空间为O(1).最坏时间复杂度 ...

  2. java排序算法(一):概述

    java排序算法(一)概述 排序是程序开发中一种非常常见的操作,对一组任意的数据元素(活记录)经过排序操作后,就可以把它们变成一组按关键字排序的一组有序序列 对一个排序的算法来说,一般从下面三个方面来 ...

  3. java排序算法(四):冒泡排序

    java排序算法(四):冒泡排序 冒泡排序是计算机的一种排序方法,它的时间复杂度是o(n^2),虽然不及堆排序.快速排序o(nlogn,底数为2).但是有两个优点 1.编程复杂度很低.很容易写出代码 ...

  4. Java排序算法(三)

    Java排序算法(三) 三.Java排序算法总结 从这三组时间复杂度对比中,可以看出,堆排序和归并排序是不管在什么情况下发挥稳定的,快速排序好的时候表现如天才,坏情况下比较差强人意,甚至在等待排序个数 ...

  5. Java排序算法(一)

    Java排序算法(一) 排序的基本概念和分类 1.1排序的定义 在<大话数据结构>中,排序定义为,假设含有n个记录的序列为{r1,r2,...,rn},其相应的关键字{k1,k2,..., ...

  6. java排序算法之冒泡排序和快速排序

    总结一下Java排序算法,以便记忆. 各类排序的时间复杂度: 排序方法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性 复杂性 直接插入排序 O(n2)O(n2) O( ...

  7. 史上最全的java随机数生成算法分享(转)

    这篇文章主要介绍了史上最全的java随机数生成算法,我分享一个最全的随机数的生成算法,最代码的找回密码的随机数就是用的这个方法 String password = RandomUtil.generat ...

  8. 常用Java排序算法

    常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...

  9. 使用Java练习算法常用的基本操作

    一.使用Java练习算法常常需要使用控制台的数据输入和输出,下面记录一下基本的使用方法: 基本用法 import java.util.*; public class Main { public sta ...

随机推荐

  1. web前端开发 --好多视频大集合--文化的传播者-杜恩德

    提醒: 如果需要的话,尽快保存,说不定哪天分享就消失了呢. 1.妙味WEB前端开发全套视频教程 链接: http://pan.baidu.com/s/1bf1Ow2 密码: 2yyu 2.极客学院前端 ...

  2. CSS3渐变相关

    背景渐变 background: -moz-linear-gradient( top,#f24652,#da2c3c); background: -o-linear-gradient(top,#f24 ...

  3. iOS 内存泄漏排查以及处理

    使用Xcode7的Instruments检测解决iOS内存泄露   文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0作为一名iOS开发攻城 ...

  4. 地理信息系统公开课计划 前言I

    对,就是地理信息系统(GIS),不是遥感RS,也不是编程,纯粹的地理信息系统. 地理信息系统=数学+物理+计算机+地理的烧脑组合. 但凡能知道.了解地理信息系统的人,基本上都不会是非知识分子,我就不矫 ...

  5. ArcGIS API for JavaScript 4.3学习笔记[新] AJS4.3和AJS3.20新特性

    今天"ArcGIS极客说"公众号推送了这两个大版本的更新,吓得我赶紧撸了一篇新博客. 这里就不写代码验证了,作为新特性小节简单介绍一下!~ AJS 4.3 1. 更强大的Featu ...

  6. Linux第六节随笔 输入输出重定向 、管道、通配符、wc / grep / tr / sort / cut / which /whereis /locate /find /

    三期第五讲 -高级文件管理1.输入输出重定向 ls -l /dev/stdin -> /proc/self/fd/0 标准输入 设备:键盘 标记:0 ls -l /dev/stdout -> ...

  7. 阅读MDN文档之CSS选择器介绍(一)

    本文为阅读MDN文档笔记 目录 Different types of Selectors Attribute Selectors Presence and value attribute select ...

  8. 3、树莓派的配置:改静态IP、连接ssh、安装中文字体、安装谷歌输入法、增加USB电流、修改触摸屏分辨率、扩展sd卡空间、修复vi和vim乱码问题、安装配置远程桌面vnc

    本博文仅作本人操作过程的记录,留作备忘.自强不息 QQ1222698 1.连接上HDMI线,插上触摸屏,插上键盘,鼠标,网线,启动.系统正常启动,但是一直闪烁,不停的黑屏,是由于触摸屏的usb口供电不 ...

  9. 【读书笔记】A Swift Tour

    素材:A Swift Tour 推荐下载Playground:Download Playground objc 自己较为熟悉,想熟悉下风头正劲的 swift.就先从官方的入门手册开始撸. 每一小节,我 ...

  10. mysql 错误信息

    1 连接MySQL错误:Can't connect to MySQL server (10060) link:>>>  http://blog.csdn.net/testcs_dn/ ...