堆的定义

堆可以看做是一种特殊的树,堆结构满足两个条件:

1、堆是一个完全二叉树。
2、堆的每一个节点的值都大于等于(或小于等于)其子节点的值。

大于等于子节点的值我们叫它:大顶堆
小于等于子节点的值我们叫它:小顶堆

大顶堆

小顶堆

非堆

不满足完全二叉树定义,不是一个堆

堆的构建

堆化

我们知道堆是一种完全二叉树,所以我们一般直接用数组来表示堆的结构,通过数组的下标就能够定位到树的任意位置,这是一种即高效又节省空间的选择。

举个例子:

数组下标中:对于第i位置的元素来说,第i2+1的位置是它的左子节点,第i2+2的位置是它的右子节点。对于每个子节点来说第(i-1)/2的位置就是它的父节点。

因此,当我们需要往堆中添加一个元素的时候,只需要直接先把元素添加到数组的最后即可,当然直接添加到数组最后就不满足堆的结构了,比如这时候要添加一个值为8,如果直接添加到数组最后显示不合适,因此我们还需要进行一些调整,而这个调整的过程一般称为堆化(heapify)。

堆化有两种,一种是自下而上,一种是自上而下。

1、向堆中添加一个元素

添加一个新的元素时,一般使用自下而上的方式,思想也比较简单,就是每次和其父节点比较,如果比父节点大,就交换,并继续与其父节点比较,直到比其父节点小,或者已经找到最顶层。

代码示例:

public class MyHeap {private int[] heapArr;private final int capacity;private int heapSize;public MyHeap(int capacity) {// 初始化数组大小heapArr = new int[capacity];// 初始化堆的大小this.capacity = capacity;// 初始化堆的当前大小heapSize = 0;}public void push(int val) {// 超过了堆的大小if (heapSize == capacity) {return;}// 先放到数组最后一位heapArr[heapSize] = val;heapInsert(heapArr, heapSize++);}private void heapInsert(int[] arr, int idx) {// 用当前节点和其父节点进行比较,如果比父节点大则进行交换,再继续比较。while (arr[idx] > arr[(idx - 1) / 2]) {swap(arr, idx, (idx - 1) / 2);idx = (idx - 1) / 2;}}private void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}

2、从堆中取出一个元素

堆化的另一种就是自上而下的,比如要从大顶堆中取出一个最大的数,那就直接从堆顶取即可,但取完之后,肯定还需要从其左子节点或者右子节点中取出一个较大的变成新的堆顶值,依次向下类推。

比如当前堆是这样的,我们现在需要取出最大的值,也就是9

过程应该是把较大的子节点向上移,也就是8,然后再把8下面的子节点中较大的向上移,最后变成这样。

但是这边有个问题就是,你应该已经看出来了,最后的结果已经不满足堆的条件了(不是完全二叉树)。

所以实际上我们需要改变一下思路,每次应当把最后一个节点的值放到最上面,然后再进行判断就好了。

第一步应该是这样,把最后一个节点3移上来。

然后进行判断,所以最后应该是这样,保持了大顶堆的结构。

代码示例:

 // 取出堆顶的值public int pop() {int ans = heapArr[0];swap(heapArr, 0, --heapSize);heapify(heapArr, 0, heapSize);return ans;}private void heapify(int[] heapArr, int idx, int heapSize) {// 拿到当前节点的左子节点int left = idx * 2 + 1;// 如果左子节点的下标超过当前堆的大小,说明当前节点已经没有子节点了。while (left < heapSize) {// 用于存放,左右子节点中,较大的节点值int largest;// 看看是否存在右子节点,如果不存在直接取左子节点为较大的节点即可if (left + 1 == heapSize) {largest = left;} else {// 取左右子节点中较大的一个largest = heapArr[left] > heapArr[left + 1] ? left : left + 1;}// 取出子节点中较大的一个,再与父节点比较,看看谁大largest = heapArr[largest] > heapArr[idx] ? largest : idx;// 如果 largest == idx 说明左右子节点都不比自己大了if (largest == idx) {break;}// 把子节点中较大的交换上去swap(heapArr, largest, idx);// 重新赋值idx位置idx = largest;// 继续从子节点的左子节点开始判断left = idx * 2 + 1;}}

堆的应用场景

下篇文章中我们在看看堆有哪些应用场景:数据结构与算法—堆的应用场景

数据结构与算法---堆的基本操作相关推荐

  1. 数据结构与算法 | 堆

    二叉树的顺序结构 堆的概念及结构 堆的实现 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费.而完全二叉树更适合使用顺序结构存储.现实中我们通常把堆(一种二叉树)使用 ...

  2. 数据结构与算法——堆的原理和实现

    目录 一.堆的原理 二.堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一.堆 ...

  3. 数据结构与算法—堆(heap)

    目录 堆 1.插入 2.删除 建堆 1.堆化 2.排序 与快速排序比较 堆的应用 一.优先级队列 1.合并有序小文件: 2.高性能定时器 二.求Top K和中位数 1.TopK问题 2.利用堆求中位数 ...

  4. 数据结构与算法 / 堆结构

    一.基本信息 1.本质 一颗特殊的树. 2.特性 完全二叉树. 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值. 3.分类 对于每一个节点的值都大于等于子节点的值的情况,该堆被称为 ...

  5. 数据结构与算法(4)——优先队列和堆

    前言:题图无关,接下来开始简单学习学习优先队列和堆的相关数据结构的知识: 前序文章: 数据结构与算法(1)--数组与链表(https://www.jianshu.com/p/7b93b3570875) ...

  6. 【数据结构与算法】堆

    一:如何理解"堆" 1,堆是一个完全二叉树: 完全二叉树要求除了最后一层,其他层的节点都是满的,最后一层的节点都靠左排列. 2,堆中每个节点都必须大于等于(或小于等于)其子树中每个 ...

  7. java树的基本知识_Java数据结构和算法(二)树的基本操作

    Java数据结构和算法(二)树的基本操作 一.树的遍历 二叉树遍历分为:前序遍历.中序遍历.后序遍历.即父结点的访问顺序 1.1 前序遍历 基本思想:先访问根结点,再先序遍历左子树,最后再先序遍历右子 ...

  8. 数据结构与算法之美笔记——基础篇(中):树,二叉树,二叉查找树,平衡二叉查找树,红黑树,递归树,堆

    树: A 节点就是 B 节点的父节点,B 节点是 A 节点的子节点.B.C.D 这三个节点的父节点是同一个节点,所以它们之间互称为兄弟节点.我们把没有父节点的节点叫作根节点,也就是图中的节点 E.我们 ...

  9. 数据结构与算法-2-链表的基本操作-查找

    数据结构与算法-2-链表的基本操作-查找(c语言) 本文是单链表的C语言实现方法,包括单链表的创建.插入.删除.修改.查找等基本操作. 链表结点的类型定义 /*链式存储结构的头结点*/ typedef ...

最新文章

  1. 南大新规:博士生在公众号发文且阅读量超1万即可参评国奖!
  2. varchar和nvarchar的区别
  3. 北京铁路局百余列普速列车将开通WiFi
  4. 使用Lucene分词
  5. idea查看项目pid_idea启动时的端口号
  6. python3键盘事件_python+selenium3 鼠标事件和键盘事件
  7. # RSA 公钥加密算法
  8. 值得收藏的图片网站,设计素材不愁,还能承包你一年壁纸
  9. Java 中文乱码问题
  10. jdbc执行多条sql_JDBC相关知识总结
  11. C# Out 传值
  12. Nancy之静态文件处理
  13. 三菱Q系列PLC程序,该设备由24个伺服电机、1套焊接机、2套CCD、4套扫码枪、6套位移传感器组成
  14. verilog——三八译码器
  15. iOS IAP 服务器二次验证突然断网了怎么办
  16. IOS – OpenGL ES 图像柏林噪点/花边噪点 GPUImagePerlinNoiseFilter
  17. 联想小新V1070-FXSE(FX版)怎么重装系统教程
  18. C# 串口CRC CCITT-FALSE 校验
  19. android9使用type-c接口,插入线控耳机与数据线监听混乱
  20. 如何在Windows和centOS系统之间实现复制粘贴?步骤如下

热门文章

  1. 【IOS】iOS开发常用三方库、插件、知名博客等等
  2. gsa系列视频监控服务器,GSA:5G设备数量突破500个
  3. Excel如何快速删除隐藏表
  4. yolo数据增强以及批量修改图片和xml名
  5. Java计算机毕业设计大学生学科竞赛报名管理系统源码+系统+数据库+lw文档
  6. python实现牛顿法和梯度下降法求解对率回归_最优化问题中,牛顿法为什么比梯度下降法求解需要的迭代次数更少?...
  7. 使用python实现跨年烟花代码
  8. css选择器获取文本,如何获取文本的CSS选择器
  9. 【计算机基础】静态链接与动态链接
  10. [更新]用最先进的理念打造最特别的串口调试工具--听风(原Wise#Pragma)