最近看了很多算法,发现堆排序居然是解题的基础,虽然看堆排序的图解我能看懂,但是让我自己去实现,发现写不出来,顾在此总结前辈的经验,供自己学习之用。

堆排序是一种树形选择排序方法,它的特点是:在排序的过程中,将array[0,...,n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(最小)的元素。

1. 若array[0,...,n-1]表示一颗完全二叉树的顺序存储模式,则双亲节点指针和孩子结点指针之间的内在关系如下:

  任意一节点指针 i:父节点:i==0 ? null : (i-1)/2

            左孩子:2*i + 1

            右孩子:2*i + 2

2. 堆的定义:n个关键字序列array[0,...,n-1],当且仅当满足下列要求:(0 <= i <= (n-1)/2)

      ① array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 称为小根堆;

      ② array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 称为大根堆;

3. 建立大根堆:

  n个节点的完全二叉树array[0,...,n-1],最后一个节点n-1是第(n-1-1)/2个节点的孩子。对第(n-1-1)/2个节点为根的子树调整,使该子树称为堆。

  对于大根堆,调整方法为:若【根节点的关键字】小于【左右子女中关键字较大者】,则交换。

  之后向前依次对各节点((n-2)/2 - 1)~ 0为根的子树进行调整,看该节点值是否大于其左右子节点的值,若不是,将左右子节点中较大值与之交换,交换后可能会破坏下一级堆,于是继续采用上述方法构建下一级的堆,直到以该节点为根的子树构成堆为止。

  反复利用上述调整堆的方法建堆,直到根节点。

4.堆排序:(大根堆)

  ①将存放在array[0,...,n-1]中的n个元素建成初始堆;

  ②将堆顶元素与堆底元素进行交换,则序列的最大值即已放到正确的位置;这就是为什么堆排序属于选择排序,每次都会产生一个最大或最小的元素。

  ③但此时堆被破坏,将堆顶元素向下调整使其继续保持大根堆的性质,再重复第②③步,直到堆中仅剩下一个元素为止。

堆排序算法的性能分析:

  空间复杂度:o(1);

  时间复杂度:建堆:o(n),每次调整o(log n),故最好、最坏、平均情况下:o(n*logn);

  稳定性:不稳定

算法实现:

如《插入排序(Insertsort)之Java实现》一样,先实现一个数组工具类。代码如下:

package sortTest;/**** @author zhengchao*/public class ArrayUtils {  //先实现一个数组工具类,打印数组public static void printArray(int[] array) {  System.out.print("{");  for (int i = 0; i < array.length; i++) {  System.out.print(array[i]);  if (i < array.length - 1) {  System.out.print(", ");  }  }  System.out.println("}");  }  //交换数组的两个元素public static void exchangeElements(int[] array, int index1, int index2) {  int temp = array[index1];  array[index1] = array[index2];  array[index2] = temp;  }
}  

堆排序中最重要的算法就是maxHeap,该函数假设一个元素的两个子节点都满足最大堆的性质(左右子树都是最大堆),只有根元素可能违反最大堆性质,那么把该元素以及左右子节点的最大元素找出来,如果该元素已经最大,那么整棵树都是最大堆,程序退出,否则交换跟元素与最大元素的位置,继续调用maxHeap原最大元素所在的子树。该算法是分治法的典型应用。具体代码如下:

package sortTest;/**** @author zhengchao*/
public class HeapSort {  public static void main(String[] args) {int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3,1 ,0,-12};  System.out.println("Before heap sort:");  ArrayUtils.printArray(array);  heapSort(array);  System.out.println("After heap sort:");  ArrayUtils.printArray(array);  }  public static void heapSort(int[] array) {  if (array == null || array.length <= 1) {  return;  }  //建立大根堆buildMaxHeap(array);  for (int i = array.length - 1; i >= 1; i--) {  //每次将顶部的元素与length - 1,length - 2.....的位置的元素交换,这样末尾的元素都是有序的了ArrayUtils.exchangeElements(array, 0, i);  //顶部元素交换后,破坏了堆的结构,重新调整maxHeap(array, i, 0);  }  }  //建立大根堆private static void buildMaxHeap(int[] array) {  if (array == null || array.length <= 1) {  return;  }  //这个地方有人可能有疑问:为什么从array.length / 2开始,你需要深刻理解二叉树的结构,并且此算法是:取每个父节点和其对应的两个子节点比,int half = array.length / 2;  for (int i = half; i >= 0; i--) { maxHeap(array, array.length, i);  }  }  //当前节点和其两个子节点A,B比较,若A,B中较大数比如是array[A]大于当前节点的数,交换当前节点与array[A]。private static void maxHeap(int[] array, int heapSize, int index) {  int left = index * 2 + 1;  int right = index * 2 + 2;  int largest = index;  if (left < heapSize && array[left] > array[index]) {  largest = left;  }  if (right < heapSize && array[right] > array[largest]) {  largest = right;  }  if (index != largest) {  ArrayUtils.exchangeElements(array, index, largest);  maxHeap(array, heapSize, largest);  }  }
}  
输出结果:
run:
Before heap sort:
{9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, 1, 0, -12}
After heap sort:
{-12, -3, -2, -1, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9}
成功构建 (总时间: 0 秒)

java ~ 堆排序相关推荐

  1. java 堆排序算法_堆排序算法的讲解及Java版实现

    这篇文章主要介绍了堆排序算法的讲解及Java版实现,堆排序基于堆这种数据结构,在本文中对堆的概念也有补充介绍,需要的朋友可以参考下 堆是数据结构中的一种重要结构,了解了"堆"的概念 ...

  2. java堆排序图解_108-堆排序的思路图解_清华毕业老程序员亲授通俗易懂的Java数据结构和算法​​​​教程_Java视频-51CTO学院...

    2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2) ...

  3. java堆排序工具包_JAVA 排序工具类

    提供了以下排序:冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 桶排序 堆排序 package com.xingej.algorithm.sort;import java.util.Arr ...

  4. Java堆排序递归_大顶堆第二弹----堆排序(递归实现)

    1 packagecom.datastruct;2 3 importjava.util.ArrayList;4 importjava.util.Arrays;5 6 public classBigHe ...

  5. java堆排序解决topk问题,利用堆排序来解决topK问题

    在这里利用了C++的几个函数(这几个API接口需要algorithm): 分享一下如何使用STL里的heap(堆)算法.堆是一个完全二叉树.在STL中,heap是算法的形式提供给我们使用的.包括下面几 ...

  6. java堆排序解决topk问题,详解堆排序解决TopK问题

    上次介绍了堆排序,这次介绍堆排序常见的应用场景TopK问题. 利用堆求TopK问题TopK问题是一个堆排序典型的应用场景. 题目是这样的:假设,我们想在大量的数据,如 100 亿个整型数据中,找到值最 ...

  7. Java堆排序(大顶堆小顶堆及应用实例)

    自己理解所得,如有错误欢迎随时指摘: 目录: 堆概念 堆结构 堆排序步骤 大顶堆代码.小顶堆代码 实际应用及实例代码 小顶堆删除图解代码.插入代码 小顶堆插入图解 时间复杂度分析 1.百度->概 ...

  8. JAVA堆排序有监视哨吗_数据结构-各类排序算法总结

    各类排序算法总结 一. 排序的基本概念 排序(Sorting)是计算机程序设计中的一种重要操作,其功能是对一个数据元素集合或序列重新排列成一个按数据元素某个项值有序的序列. 有 n 个记录的序列{R1 ...

  9. 最新出炉!java堆排序图解

    美团技术一面20分钟 晚7点,因为想到下周一才面试,我刚准备出去打个羽毛球,北京的电话就来了.面试官各种抱歉,说开会拖延了. 1.自我介绍 说了很多遍了,很流畅捡重点介绍完. 2.问我数据结构算法好不 ...

最新文章

  1. NR 5G NG-AP(NG接口)介绍
  2. 华为OJ 名字美丽度
  3. 设CPU中各部件及其相互连接关系如下图所示。图中W是写控制标志,R是读控制标志,R 1 和R 2 是暂存器
  4. 寒假每日一题(入门组)【week6 完结】
  5. Disgruntled Judge UVA - 12169
  6. QT的QQmlApplicationEngine类的使用
  7. php unset 多可以什么_php unset()销毁单个或多个变量
  8. java中的基本数据类型_Java中的基本数据类型和引用数据类型
  9. C++中的指针与引用(转)
  10. 应用实践 | 南方科技大学研发基于新型冠状病毒知识图谱模式挖掘系统
  11. 黑马程序员--C语言基础之--sizeof()运算符的使用以及注意
  12. 【综合】JS跨域方案JSONP与CORS跨域
  13. 和屌丝一起学cocos2dx-CCScrollView
  14. 《PhoneGap移动应用开发手册》——1.5节获取设备位置传感器信息
  15. 【组合数学】错排问题 ( 递推公式 | 通项公式 | 推导过程 ) ★
  16. 军犬舆情每日热点:台湾海峡发生6.2级地震;泉州通报碳九泄漏事件处理结果
  17. 音视频开发之基于某三方音效的Android native层四声道音频输出
  18. 在Codesys用ST语言基于链表实现栈LIFO数据结构详细说明+代码实例
  19. python程序设计入门书籍推荐_python刚刚入门,接下来这几本python的书会让你成为别人眼里的大神!...
  20. LaTeX 图片加标题 文本分栏自动换行

热门文章

  1. IPXE+WinPE+Ghost+VHD+极域在机房维护中的应用
  2. Java动态代理(以现实中我们熟悉的中介代理租房、卖房模式理解)(附案例详解)
  3. 安卓app开发零基础入门培训!腾讯Android开发面试记录,技术详细介绍
  4. 使用wandb可视化Scikit-Learn模型
  5. 高等数学特训班 [MP4] (5.63G)
  6. oracle 55道练习题
  7. oracle 误删数据找回,关于oracle找回误删数据
  8. java负载均衡插件_超级负载均衡
  9. 灵性图书馆:好书推荐-《内在的探索》
  10. cad中怎么随意移动图形_cad中怎么随意移动图形_绘制CAD图纸的过程中CAD快捷键失灵了怎么办?...