最大堆的解释见:http://www.java3z.com/cwbwebhome/article/article1/1362.html?id=4745

这里是整理后的代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;import com.dm.core.structure.tupler.StrDoubleTuple;/*** 最大堆,用作优先队列的TOPK查找<br>* 原理:每个节点的值都>=其左右孩子(如果有的话)值的完全二叉树* * @author Anthony* @param <T>*/
public class MaxHeap<T> {/*** 堆数据*/private List<T> heap;/*** 堆数据的比较对象*/private Comparator<T> comparator;public MaxHeap(List<T> heap) {this(heap, new Comparator<T>() {@SuppressWarnings("unchecked")@Overridepublic int compare(T o1, T o2) {return ((Comparable<T>) o1).compareTo(o2);}});}public MaxHeap(List<T> heap, Comparator<T> comparator) {super();this.heap = heap;this.comparator = comparator;}/*** 向最大堆中插入元素,添加到数组的尾部,然后上升操作* * @param value*/public void insert(T value) {// 数组下标为0的位置不放元素if (heap.size() == 0)heap.add(null);heap.add(value);up(heap.size() - 1);}/*** 节点上升递归实现<br>* 由于新插入的数是在数组尾部,所以需要做上升操作,让插入的数和父节点的值比较,当大于父节点的时候交换* * @param index*/private void up(int index) {// 注意堆是从下标为1开始,当index=1的时候,已经是根节点了if (index <= 1)return;int parent = index / 2; // 父节点T parentValue = heap.get(parent);T indexValue = heap.get(index);if (comparator.compare(parentValue, indexValue) < 0) {swap(parent, index);up(parent);}}/*** 节点上升非递归实现* * @param index*/@SuppressWarnings("unused")private void up2(int index) {int parent = 0;for (; index > 1; index /= 2) {parent = index / 2;T parentValue = heap.get(parent);T indexValue = heap.get(index);if (comparator.compare(parentValue, indexValue) < 0)swap(parent, index);}}/*** 交换a和b的位置* * @param a* @param b*/private void swap(int a, int b) {T temp = heap.get(a);heap.set(a, heap.get(b));heap.set(b, temp);}/*** 删除堆中位置是index处的值<br>* 原理是:当删除节点时,原来的位置就会出现一个孔,填充这个孔的方法就是,把最后的叶子赋给该孔,然后把该叶子删除* * @param index*/public void delete(int index) {heap.set(index, heap.get(heap.size() - 1));down(index);heap.remove(heap.size() - 1);}/*** 节点下沉递归实现<br>* 删除数据的时候,由于是用的尾部的数据(基本上是最小值)填充,所以需要做下沉操作* * @param index*/public void down(int index) {int n = heap.size() - 2; // 因为最后一个节点已经挪至index位置,所以已经是废弃叶子节点,不再考虑int child = 2 * index;// 说明该节点没有左右儿子节点了,那么无须下沉,直接返回if (child > n)return;// 如果左右儿子都存在,取值较大的那个儿子节点if (child < n&& comparator.compare(heap.get(child), heap.get(child + 1)) < 0)child++;// 如果该节点小于较大的那个儿子,那么下沉if (comparator.compare(heap.get(index), heap.get(child)) < 0) {swap(child, index);down(child);}}/*** 节点下沉非递归实现* * @param index*/public void down2(int index) {T temp = heap.get(index);int n = heap.size() - 2;int child = 0;for (; 2 * index <= n; index = child) {child = 2 * index;if (child < n&& comparator.compare(heap.get(child), heap.get(child + 1)) < 0)child++;if (comparator.compare(temp, heap.get(child)) < 0)swap(child, index);elsebreak;}}/*** 根据树的性质建堆,树节点前一半一定是分支节点,即有孩子的,所以我们从这里开始调整出初始堆* * @param heap*/public void adjust() {for (int i = heap.size() / 2; i > 0; i--)adjust(i, heap.size() - 1);}/*** 调整堆,使其满足最大堆得定义<br>* 具体调整过程为: 从最后一个分支结点(n/2)开始,到根(1)为止,依次对每个分支结点进行调整(下沉)<br>* 以便形成以每个分支结点为根的堆,当最后对树根结点进行调整后,整个树就变成了一个堆* * @param i* @param n*/public void adjust(int i, int n) {int child = 0;for (; i <= n / 2;) {child = i * 2;if (child < n&& comparator.compare(heap.get(child), heap.get(child + 1)) < 0)child++;if (comparator.compare(heap.get(i), heap.get(child)) < 0) {swap(i, child);i = child; // 交换后,以child+1为根的子树不一定满足堆定义,所以从child处开始调整} elsebreak;}}/*** 堆排序,从尾部开始,将每个节点和根节点交换,然后调整节点之上的子堆*/public void sort() {for (int i = heap.size() - 1; i > 0; i--) {swap(1, i);adjust(1, i - 1);}}public static void main(String args[]) {List<Integer> array = new ArrayList<Integer>(Arrays.asList(null, 1, 2,5, 10, 3, 7, 11, 15, 17, 20, 9, 15, 8, 16));MaxHeap<Integer> mh = new MaxHeap<Integer>(array);mh.adjust();System.out.println("调整后的初始堆:" + array);mh.delete(8);System.out.println("删除下标8之后的堆:" + array);mh.insert(99);System.out.println("添加值99之后的堆:" + array);mh.sort();System.out.println("排序后的堆:" + array);List<StrDoubleTuple> list = new ArrayList<StrDoubleTuple>();list.add(null);list.add(new StrDoubleTuple("a", 1.0));list.add(new StrDoubleTuple("a", 2.0));list.add(new StrDoubleTuple("a", 5.0));list.add(new StrDoubleTuple("a", 10.0));list.add(new StrDoubleTuple("a", 3.0));list.add(new StrDoubleTuple("a", 7.0));list.add(new StrDoubleTuple("a", 11.0));list.add(new StrDoubleTuple("a", 15.0));list.add(new StrDoubleTuple("a", 17.0));list.add(new StrDoubleTuple("a", 20.0));list.add(new StrDoubleTuple("a", 9.0));list.add(new StrDoubleTuple("b", 15.0));list.add(new StrDoubleTuple("a", 8.0));list.add(new StrDoubleTuple("a", 16.0));MaxHeap<StrDoubleTuple> mho = new MaxHeap<StrDoubleTuple>(list);mho.adjust();System.out.println("调整后的初始堆:" + list);mho.delete(8);System.out.println("删除下标8之后的堆:" + list);mho.insert(new StrDoubleTuple("a", 99.0));System.out.println("添加值99之后的堆:" + list);mho.sort();System.out.println("排序后的堆:" + list);}
}

  

转载于:https://www.cnblogs.com/AnthonyViking/p/3623529.html

最大堆的Java实现相关推荐

  1. 手写最大堆(Java实现)

    最大堆 最大堆和最小堆是二叉堆的两种形式. 最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大. 最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小 ...

  2. Java数据结构与算法:堆

    1. 堆的定义 设有n个数据元素的关键字为(k0.k1.-.kn-1),如果它们满足以下的关系:ki<= k2i+1且ki<= k2i+2(或ki>= k2i+1且ki>= k ...

  3. 数据结构-堆实现优先队列(java)

    队列的特点是先进先出.通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西.但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出.这就很像堆的特 ...

  4. java 二叉堆_二叉堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了二叉堆,本章给出二叉堆的Java版本.还是那句话,它们的原理一样,择其一了解即可. 二叉堆的介绍 二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两 ...

  5. 随便说说---java初级学习路线

    一哥们(代号三鳖)搞android的,有一段儿学ios,最近脑子抽风,又想学java后端,所以抽空给那货整理了一下学习路线,当然仅限参考,这货自己能找,就是不烦你他不舒服,擦~ 1 培训机构的课程表 ...

  6. 使用java代码发送zip文件到邮箱_Azkaban安装与使用(下)

    01 PART Azkaban进阶 JavaProcess作业类型案例 JavaProcess类型可以运行一个自定义主类方法,type类型为javaprocess,可用的配置为: Xms:最小堆  9 ...

  7. Java中的堆分配参数总结《对Java的分析总结》(二)

    <对Java的分析总结>-Java中的堆分配参数总结 header 配制说明 -Xms: 设置Java应用程序启动时的初始堆大小 -Xmx: 设置Java应用程序能获得的最大堆大小 -Xs ...

  8. java日志框架JUL、JCL、Slf4j、Log4j、Log4j2、Logback 一网打尽

    为什么程序需要记录日志 我们不可能实时的24小时对系统进行人工监控,那么如果程序出现异常错误时要如何排查呢?并且系统在运行时做了哪些事情我们又从何得知呢?这个时候日志这个概念就出现了,日志的出现对系统 ...

  9. 三天刷完《剑指OFFER编程题》--Java版本实现(第三天)

    正在更新中......... 剑指offer --Python版本的实现: 剑指offer(1/3)第一大部分 剑指offer(2/3)第二大部分 剑指offer(3/3)第三大部分 -------- ...

最新文章

  1. jmeter—操作数据库
  2. Bash脚本获取自身完整路径的可靠方法
  3. RetrieveFavicon 获取任何站点的 favicon
  4. HTMLCSS 问题
  5. ASP.NET中常用的26个优化性能方法(1-10)
  6. 文件服务器ping延时大,windowns 2008 ping 127.0.0.1延迟大的解决方法。
  7. mysql大数据表无主键_oracle转mysql 表没有主键
  8. 澳大利亚超市巨头考虑设专门网站 方便代购买奶粉
  9. 首个 Ubuntu 平板将于今年秋天面世
  10. 提取已有的内核配置文件
  11. 树莓派raspberrypi系统安装docker以及编译nginx和php镜像
  12. 有意思、值得思考的文章记录
  13. word公式编辑器输入斜体
  14. 大型即时通讯系统微信、陌陌架构分析全记录!
  15. 『矩阵论笔记』详解最小二乘法(矩阵形式求导)+Python实战
  16. 中科柏诚与知名上市公司南天信息(000948)签署战略合作协议
  17. Java高级面试-面经
  18. 273 块钱购入的域名,值了
  19. 金庸小说数据化中的部分题目答案
  20. java第10章总结

热门文章

  1. workbench拓扑优化教程_workbenchds拓扑优化分析.ppt
  2. 【FFMPEG源码终极解析】 avformat_open_input (一)
  3. 字符串操作之字符串连接
  4. python学什么版本2020年_2020年了居然还有人在学Python?学python有什么用?
  5. 使用计算机的女士,3款女性专用PC 将美丽进行到底
  6. 二分查找递归与非递归的时间比较_我们说一说Python的查找算法!
  7. 电信级E1保护倒换设备产品介绍
  8. 怎么样解决小交换机引起的路由环路故障?
  9. 光纤交换机按照级别可分为3种
  10. HDMI光端机基本知识及相关品牌介绍