目录

  • 一、堆的概念
  • 二、堆的操作
    • 向下调整(以小堆为例)
    • 向上调整(以大堆为例)
    • 建堆
  • 三、堆的应用
    • 优先级队列(Priority Queue)
      • 入队列操作
      • 出队列操作
      • 代码实现

一、堆的概念

  • 逻辑上是一棵完全二叉树
  • 物理上是保存在数组中
  • 满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆
  • 满足任意结点的值都小于其子树中结点的值,则是小堆,或者小根堆,或者最小堆
  • 堆的基本作用是,快速找集合中的最值

二、堆的操作

向下调整(以小堆为例)


思路:伪代码分析

public static void 向下调整(int[] array, int size, int index) {1.判断 index 对应的下标是不是叶子结点如果是叶子结点,直接 return2.找到两个孩子中最小的3.最小的孩子的值和 index 对应位置的值比较<              接着进行下一步==     >        满足堆的性质,直接 return4.交换最小的孩子的值和 index 的值5.把最小的孩子视为 index,循环回去(从步骤 1,继续往下走)
}

引出的问题:

  1. 怎么判断 index 对应的位置是不是叶子结点 ?
  2. 怎么找最小的孩子?
  3. 小堆是有序的吗?有序的是小堆吗?
    小堆不一定是有序的,但有序的一定是小堆。

代码实现:

public class HeapTest {public static void shiftDown(int[] array, int size, int index) {while (true) {//1.判断 index 对应的下标是不是叶子结点int leftIndex = 2 * index + 1;if(leftIndex >= size) {return;}//2.找到两个孩子中最小的int minIndex = leftIndex;int rightIndex = leftIndex + 1;if(rightIndex < size && array[rightIndex] < array[leftIndex]) {minIndex = rightIndex;}//3.最小的孩子的值和 index 对应位置的值比较if(array[index] <= array[minIndex]) {return;}//4.交换最小的孩子的值和 index 的值int temp = array[index];array[index] = array[minIndex];array[minIndex] = temp;//5.把最小的孩子视为 index,循环回去(从步骤 1,继续往下走)index = minIndex;}}
}

向上调整(以大堆为例)

思路:伪代码分析

public static void adjustUp(int[] array,int size,int index) {1.判断 index 是不是树的根,如果是根,调整结束2.找到 index 的父结点3.比较父结点的值和 index 的值4.只要父结点的值 <= index,调整结束5.交换父结点和 index 的值6.把父结点看做 index,继续这个大循环
}

代码实现:

public class HeapTest {public static void adjustUp(int[] array,int size,int index) {while (true) {//1.判断 index 是不是树的根,如果是根,调整结束if(index == 0) {break;}//2.找到 index 的父结点int parentIndex = (index - 1) / 2;//3.比较父结点的值和 index 的值//4.只要父结点的值 <= index,调整结束if(array[parentIndex] <= array[index]) {break;}//5.交换父结点和 index 的值int temp = array[index];array[index] = array[parentIndex];array[parentIndex] = temp;//6.把父结点看做 index,继续这个大循环index = parentIndex;}}
}

建堆

思路:伪代码分析

public static void createHeap(int[] array, int size) {size-1 树最后一个结点的下标((size-1)-1)/2    从[(size-2)/2,0] 不断地进行向下调整
}

代码实现:

public static void createHeap(int[] array, int size) {//找到层序遍历的最后一个结点下标int lastIndex = size - 1;//找到最后一个结点的父节点的下标int lastParentIndex = lastIndex - 1 / 2;//从[(size-2)/2,0] 不断地进行向下调整for(int i = lastParentIndex; i >= 0; i++) {shiftDown(array,size,i);}
}

三、堆的应用

堆的应用有挺多:优先级队列、堆排序、TopK

堆排序TopK就先不浅析了,会写博客专门去分析理解,在这里就简要分析一下。

堆排序

分为两个步骤:

  1. 用当前需要排序的数据构建一个堆
  2. 不断的弹出当前堆的堆顶元素,因为小顶堆的堆顶元素一定是最小的,即可以用于排序。堆排序的本质就是,把数据构建成堆之后,弹出堆顶元素,然后互换堆顶元素和最后一个元素,不断对当前堆进行自顶向下的堆的调整,然后继续弹出。

TopK

TopK一般解决的是求解前K个最大或者最小的元素,或第K个最大或最小的元素。

拿到这类问题,我们的第一想法肯定是排序求解。但排序还会浪费一定的资源排序前K个元素,为了节省计算资源,我们需要思考的是怎么优化,聪明的你肯定想到了,是不是这最大的k个元素也不需要排序呢?

为此,我们需要构建包含K个元素的小顶堆,这个小顶堆用于存储,当前最大的k个元素。接着我们需要从第 k+1个元素开始扫描,如果被扫描的元素大于堆顶,则替换堆顶的元素,并调整堆,以保证堆内的k个元素,总是当前最大的k个元素。扫描完所有n-k个元素,最终堆中的k个元素,就是优化后求的TopK。


优先级队列(Priority Queue)

入队列操作

过程(以大堆为例):


出队列操作

过程(以大堆为例):


代码实现

public class MyPriorityQueue {private Integer[] array;private int size;public MyPriorityQueue() {array = new Integer[100];size = 0;}public Integer element() {if(size == 0) {throw new RuntimeException("空的");}return array[0];}/*** 入队列*/public void add(Integer e) {array[size] = e;size++;adjustUp(size-1);}public void adjustUp(int index) {while (true) {if(index == 0) {break;}int parentIndex = (index - 1) / 2;if(array[parentIndex] <= array[index]) {break;}int temp = array[index];array[index] = array[parentIndex];array[parentIndex] = temp;index = parentIndex;}}/*** 出队列*/public Integer remove() {if(size == 0) {throw new RuntimeException("空的");}int e = array[0];array[0] = array[size - 1];size--;adjustDown(0);return e;}private void adjustDown(int index) {while (true) {int leftIndex = 2 * index + 1;if(leftIndex >= size) {return;}int minIndex = leftIndex;int rightIndex = leftIndex + 1;if(rightIndex < size && array[rightIndex] < array[leftIndex]) {minIndex = rightIndex;}if(array[index] <= array[minIndex]) {return;}int temp = array[index];array[index] = array[minIndex];array[minIndex] = temp;index = minIndex;}}
}

测试类:

public class PriorityQueueDemo {public static void main(String[] args) {MyPriorityQueue queue = new MyPriorityQueue();queue.add(3);queue.add(5);queue.add(2);queue.add(7);System.out.println(queue.remove());//2System.out.println(queue.remove());//3System.out.println(queue.remove());//5System.out.println(queue.remove());//7}
}

运行结果:


堆(Heap) 浅析相关推荐

  1. 一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc

    大家好,我是无际. 有一周没水文了,俗话说夜路走多了难免遇到鬼. 最近就被一个热心网友喷了. 说我的文章没啥营养,所以今天来一篇烧脑的. 哈哈,开个玩笑,不要脸就没人能把我绑架. 主要是最近研发第二代 ...

  2. JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )(转发)

    这两天看了一下深入浅出JVM这本书,推荐给高级的java程序员去看,对你了解JAVA的底层和运行机制有 比较大的帮助. 废话不想讲了.入主题: 先了解具体的概念: JAVA的JVM的内存可分为3个区: ...

  3. 栈(stack)和堆(heap)

    栈(stack)和堆(heap), Java程序在运行时都要开辟空间,任何软件在运行时都要在内存中开辟空间,Java虚拟机运行时也是要开辟空间的.JVM运行时在内存中开辟一片内存区域,启动时在自己的内 ...

  4. (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack)(C/C++存储类型总结)(内存管理)

    文章目录 bss段 data段 text段 堆(heap) 栈(stack) 一个程序本质上都是由 bss段.data段.text段三个组成的. 存储类型总结 bss段 bss段(bss segmen ...

  5. codeforces 贪心+优先队列_算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)...

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值:

  6. Java里的堆(heap)栈(stack)和方法区(method)

    http://imiduo.iteye.com/blog/616310 Java里的堆(heap)栈(stack)和方法区(method)  <一> 基础数据类型直接在栈空间分配, 方法的 ...

  7. SQL Server 堆heap 非聚集索引 Nonclustered index 行号键查找RID loopup结合执行计划过程详解

    SQL Server 堆型数据与执行计划使用案例 索引的相关术语 1 堆(Heap)是一种没有指定排序的数据结构,通俗的理解堆就像是按照顺序排放的杂物.在数据库里也即是对应没有聚集索引. 2 聚集索引 ...

  8. java中堆栈(stack)和堆(heap)

    http://www.ej38.com/showinfo/java-172156.html 堆栈是一种先进后出的数据结构,只能在一端进行输入或输出数据的操作  Stack类在java.util包中 向 ...

  9. JVM之堆Heap参数调优入门

    JVM之堆Heap参数调优入门 目录: JVM体系结构概览 JVM之堆Heap参数调优入门 2.1 java7和 java8堆结构图 2.2 堆内存调优简介 1. JVM体系结构概览 2. JVM之堆 ...

最新文章

  1. 【深度学习】基于深度神经网络进行权重剪枝的算法(一)
  2. git 查看某个文件的历史记录
  3. 在正确的方向坚持下去,一直坚持下去,直到有成果
  4. [Jarvis OJ - PWN]——Backdoor
  5. Rocket - tilelink - Atomics
  6. win7-64bit 下oracle11g plsql 的正确安装
  7. Java Date Time 教程-System.currentTimeMillis()
  8. 电脑常见问题:能打开QQ但不能打开网页(DNS问题)
  9. 通常网站当中的关键词密度如何控制呢
  10. springboot+SSM Demo框架搭建
  11. 【傻瓜教程】Ubuntu18.04LTS安装NVIDIA驱动详细完整过程
  12. Flea CodeForces - 32C (思维)
  13. 网络协议分为哪几层---物理层,连接层,网络层,传输层,应用层详解
  14. 微软DNS服务器默认,Microsoft Windows Server DNS 配置打开地址套接字
  15. 草根大牛论道“下一代软件研发” 开启软件转型讨论大潮
  16. 记录一些面试相关的刁难题
  17. 浙江杭州工程师职称评审论文要求
  18. 大专前端实习生如何挣到月薪 20k
  19. 【Linux】Linux中的文件搜索和查看
  20. 计算机主机不能启动,电脑不启动是什么原因_电脑无法启动怎么办-win7之家

热门文章

  1. php编程模块英文缩写_php的英文全称是什么
  2. python 保留浮点数为两位小数
  3. linux中隐藏得木马程序,Linux远控分析
  4. 基于canvas实现的多功能画板
  5. Android开发关键知识点讲解
  6. CSS/HTML 如何在网页中添加空格(琐碎知识点整理)
  7. 【BZOJ】2277: [Poi2011]Strongbox
  8. 以下关于python函数说法错误的是def_以下关于Python函数的描述中,错误的是()
  9. [BZOJ4668] 冷战
  10. 数学课本上的9大变态!