最大堆的Java实现

最大堆的解释见: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle Java Mission Control:终极指南

“我们喜欢关注Mikhail Vorontsov的博客&#xff0c;并获得他对Java Performance相关问题的看法。 我们曾多次被问到Takipi的Java错误分析与Java Mission Control和Java Flight Recorder有何不同。 因此&#xff0c;尽管工具之间的差异很大&#xff08;主要是&#xff0c;JMC主…

福州大学计算机专业考研,2015年福州大学计算机考研经验贴

2015年福州大学计算机考研经验贴福州大学发布于2019年9月24日 02:18阅读数 3995一年的考研路过去了&#xff0c;从初试到复试&#xff0c;懵懵懂懂到略有所知。在此&#xff0c;不谈成绩&#xff0c;没有骄傲&#xff0c;讲点自己的经验&#xff0c;希望帮到各位。以下所有言论…

python购物车实现的功能是什么_Python3实现购物车功能

Python3实现购物车功能来源&#xff1a;中文源码网 浏览&#xff1a; 次 日期&#xff1a;2018年9月2日【下载文档: Python3实现购物车功能.txt 】(友情提示:右键点上行txt文档名->目标另存为)Python3实现购物车功能 本文实例为大家分享了Python3实现购物车功能的具体…

杭电考研计算机专业课_杭州电子科技大学计算机考研专业课平均分76.03,国家线复试是这个原因!...

杭电计算机学院是计算机类报考热门&#xff0c;2019考研英语数学开始统一采用英语一数学一&#xff0c;不分学硕专硕还是非全日制&#xff1b;今年复试线已出&#xff0c;除计算机技术专硕复试线280分&#xff0c;高于国家线&#xff0c;其余专业均是国家线270分复试&#xff1…

网络工程属于计算机哪一类,网络工程专业属于什么门类

在高考志愿填报的时很多考生和家长都不知道网络工程专业属于什么门类&#xff0c;很是影响考生的志愿填报专业选择&#xff0c;下面有途网小编根据考生的要求整理出网络工程专业属于工学类提供给大家&#xff0c;希望能够帮助考试顺利的填报好自己的专业。网络工程专业介绍专业…

[003]容器和动态数组的使用

例&#xff1a; 编写程序读入一组 string 类型的数据&#xff0c;并将它们存储在vector 中。接着&#xff0c;把该 vector 对象复制给一个字符指 针数组。为 vector 中的每个元素创建一个新的字符数 组&#xff0c;并把该 vector 元素的数据复制到相应的字符数组 中&#xff0c…

linux 查看显卡信号_Linux下如何查看NVIDIA显卡信息

匿名用户1级2015-07-28 回答lspci | grep -i vga这样就可以显示机器上的显卡信息&#xff0c;比如[rootlocalhost conf]# lspci | grep -i vga01:00.0 VGA compatible controller: nVidia Corporation Device 1081 (rev a1)02:00.0 VGA compatible controller: nVidia Corpora…

用计算机演奏打上花火,米津玄师打上花火歌词中文谐音(最好要简单全面)

满意答案.Ador2020.03.19采纳率&#xff1a;60% 等级&#xff1a;14已帮助&#xff1a;2446人打上花火 - 《升起的烟花&#xff0c;从下面看&#xff1f;还是从侧面看&#xff1f;》主题曲 词&#xff1a;米津玄师 曲&#xff1a;米津玄师xDAOKO有些地方一些音不对请见谅哈 …

Hibernate自动提交命令强制MySQL在过多的磁盘I / O中运行

亲爱的大家&#xff0c; 我敢肯定&#xff0c;你们中的许多人都在使用Hibernate和MySQL&#xff0c;我自己在这里和那里都使用它。 通常&#xff0c;编程模型是不错的&#xff0c;但是普通的JDBC可以快得多已经不是什么秘密了。 在这篇文章中&#xff0c;我想引起您的注意Hibe…

两个向量之间的夹角公式_关于平面向量夹角求参数取值范围的两种基本解法介绍...

平面向量的夹角问题是考察高中向量知识掌握程度的常考内容&#xff0c;主要涉及到的知识点是平面向量的数量积公式。在这里介绍一道常见的平面向量题目&#xff0c;通过两种最基本的解法&#xff0c;来帮助同学们理解向量之间的夹角。填空题第15题&#xff1a;设平面向量a(-2&a…

一些基本概念的总结

web窗体页&#xff1a; 可以使用web窗体页来创建可编程的web页&#xff0c;这些web页用作web应用程序的用户界面。web窗体页在任何浏览器或客户端设备中像用户提供信息&#xff0c;并使用服务器代码来时间应用逻辑。web窗体页输出几乎可以包含任何支持http的语言。 HTML控件&am…

宿迁学院的计算机系怎么样,宿迁学院是几本 学生评价怎么样好不好(10条)

宿迁学院是几本 学生评价怎么样好不好(10条)考生之前的努力奋斗就是为了高考报志愿时有更多的底气和把握。而俗话说&#xff0c;三分考、七分报&#xff0c;有很多考生和家长都还不太了解大学的一本、二本、三本之分&#xff0c;本科高校只有一个层次和等级&#xff0c;就是(本…

Google Guava:您永远不会知道的5件事

每个开发人员都可以使用哪些鲜为人知的Google Guava功能&#xff1f; 它是那里最受欢迎的库之一&#xff0c;它是开源的&#xff0c;您可能已经知道了&#xff0c;它来自人们玩Quidditch作为一项真正的运动的地方&#xff08;至少在The Internship上 &#xff09;。 它不是哈利…

hql中获取前一天的数据_PostgreSql 怎么获取数据库中关键系统信息(一)

如何通过SQL 的方式获得数据库中的一些关键信息&#xff0c;是一个DB最正常的工作&#xff0c;如何通过一些SQL来获得PG的一些关键的参数和信息或者是数据库中的一些信息是需要知道的一件事情。以下是部分 1一般来说每种数据库中都有一个或几个系统的数据库&#xff0c;在PG中s…

计算机信息技术为教育带来的变化,信息技术对课堂教学带来的变化

信息技术对课堂教学带来的变化谈一谈信息技术对教育教学的影响以及给课堂教学带来的变化龙川县培英学校 骆俊武在信息技术迅速发展的今天&#xff0c;计算机的应用、网络技术应用&#xff0c;直接影响着学校的的教育教学系统、学校的教育模式、教第一文库网师的教学方法。与传统…

abd shell关闭所有程序_一个 Shell 脚本逆袭的规范,拿走不谢

指定一个默认脚本解释器“#!” 是一个约定的标记&#xff0c;它告诉系统这个脚本需要什么解释器来执行&#xff0c;即使用哪一种Shell。他指明了当我们没有指定解释器的时候默认的解释器。为什么建议要在首行加上脚本默认解释器&#xff0c;因为有的操作系统的默认解释器不是sh…

html比赛项目,趣味运动会最新个人比赛项目

趣味运动会中也有很多个人能参加的趣味比赛项目。今天小编就与大家分享趣味运动会个人赛项目&#xff0c;仅供大家参考!趣味运动会个人赛项目一&#xff1a;《懒惰的自行车》在前面车筐上放标志规则&#xff1a;自行车在规定的跑道上(约50厘米宽&#xff0c;15米长的跑道)行驶&…

CentOS 6.3 下编译Nginx(笔记整理)

1. 安装关联程序 [rootlocalhost opt]# yum search gcc [rootlocalhost opt]# yum install gcc-c [rootlocalhost opt]# yum install make [rootlocalhost opt]# yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel2. 下载Nginx [rootlocalhost files]# ta…

unity 是厘米还是米_1种“竹节参”,植株有40厘米高,能挂果,果子成熟后变红,珍贵...

很多顽强的野生植物会在竹林里生长&#xff0c;我们都知道价值比较高的七叶一枝花、金线莲等植物&#xff0c;就会生长在湿润的竹林里&#xff0c;它们喜欢湿度比较高的环境&#xff0c;所以在其它比较潮湿的地方也有。不过还有1种“竹节参”&#xff0c;它在竹林里也是常见的&…

计算机主板diy,Pc-硬件-装机DIY-〖菜鸟入门篇〗电脑主板图解

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼主板(线路板)是如何制造出来的呢&#xff1f;PCB的制造过程由玻璃环氧树脂(Glass Epoxy)或类似材质制成的PCB“基板”开始。制作的第一步是光绘出零件间联机的布线&#xff0c;其方法是采用负片转印(Subtractive transfer)的方式将…