[数据结构学习笔记9] 堆(Heaps)

news/2025/1/8 22:54:10/文章来源:https://www.cnblogs.com/Eagle6970/p/18659402

在日常生活中,我们常常有很多想法要去实现,但是时间有限,所以要把想法分优先级,哪个是最重要的,先做它。堆(heaps)是这样一个数据结构,它让你容易(O(1))的获取最高优先级的想法,并且提供了快速(O(log n))插入,移除想法操作。

 

堆分为最大堆和最小堆,最大堆就是说root是最大值,最小堆是说root是最小值。这里我们讨论的时候,讨论最大堆。最小堆的表示和处理方式和最大堆相反。

最大堆是一个Complete 二叉树,并且每个节点值都要大于它的子节点。

 

常见堆操作

插入节点

1. 如果树为空,则新节点为root节点

2. 如果树不为空,则从左往右,一次添加新的节点

3. 比较新节点和其父节点的大小,如果新节点大于父节点,则新节点和父节点互换

4. 重复步骤3,直到父节点大于新节点

移除节点,一般堆移除节点,指的是移除root

1. 把root和最后的叶子节点互换

2. 比较新的root节点和其孩子节点,如果新root比孩子节点小,那么把新root和两个孩子节点中较大的互换;重复这个步骤,直到新root节点比它的孩子节点大

 

代码实现(javascript)

这里我们要用数组的方式去表示堆。

请看这样一个堆:

                        50

                       |      |
                     15     18

                   |      |    |     |

                 14   2    13    1

               |     |    |

               2   3    0

用数组表示成这样:

50 15 18 14 2 13 1 2 3 0
0 1 2 3 4 5 6 7 8 9

1. 下标为i的节点的父节点,计算公式 Math.floor((i-1)/2)。注意这里适用于非root节点;

2. 下标为i的节点的左子节点,计算公式 2i+1。注意这里计算不能越界;

3. 下标为i的节点的右子节点,计算公式 2i+2。同样这里也不能越界。

class Heap {constructor() {this.heap = [];}  insert(value) {this.heap.push(value);this.#bubbleUp(this.heap.length - 1);}extractMax() {if (this.heap.length === 0) {return null;}if (this.heap.length === 1) {return this.heap.pop();}    const max = this.heap[0];const end = this.heap.pop();this.heap[0] = end;this.#bubbleDown(0);return max;}#bubbleUp(index) {if (index === 0) {return;}const parentIndex = Math.floor((index - 1) / 2);if (this.heap[index] > this.heap(parentIndex)) {[this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];this.#bubbleUp(parentIndex);}}#bubbleDown(index) {const leftChildIndex = 2 * index + 1;const rightChildIndex = 2* index + 2;let largestIndex = index;if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] > this.heap[largestIndex]) {largestIndex = leftChildIndex;}if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] > this.heap[largestIndex]) {largestIndex = rightChildIndex;}if (largestIndex !== index) {[this.heap[index], this.heap[largestIndex]] = [this.heap[largestIndex], this.heap[index]];this.#bubbleDown(largestIndex);}}getMax() {return this.heap[0];}size() {return this.heap.length;}isEmpty() {return this.heap.length === 0;}
}

使用Heap

let myHeap = new Heap();
myHeap.insert(14);
myHeap.insert(18);
myHeap.insert(50);
myHeap.insert(1);
myHeap.insert(3);
myHeap.insert(15);
myHeap.insert(2);myHeap.extractMax(); // 50

时间复杂度

动作 时间复杂度 空间复杂度
移除根节点 O(log n) O(1)
插入新节点 O(log n) O(1)

堆常应用于堆排序,优先队列,迪杰斯特拉算法发现图最短路径等等。

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

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

相关文章

电源输入输出主干道的分析思路, 如何阅读Datasheet的Layout Guide方法

电源输入输出主干道的分析思路, 如何阅读Datasheet的Layout Guide方法 分析电源输入输出主干道和阅读Datasheet中的Layout Guide是电子设计中非常重要的技能。以下是关于这两个主题的详细介绍和分析思路。 一、电源输入输出主干道的分析思路 电源输入输出主干道是指连接电源输入…

判断推理学习笔记

判断推理四大题型①图形推理(难)8/10 ②类比推理 ③定义判断(10道,不要超过10分钟) ④逻辑推理(难) 图形推理的命题形式 一组图 两组图(前组找规律,后组应用规律) 九宫格(90%横着看,找规律,验证规律,应用规律;10%竖着看;米字看;S) 分组分类(三三一组) 空间…

MemoryAnalyzerTool(mat)分析dump文件

一、常见需要分析dump文件场景 1.1 fullGC频繁1.2 堆空间溢出1.3 元空间溢出二、准备工具 能分析dump文件的工具很多比如Java自带的jvisualvm、商业软件Jprofile、mat(MemoryAnalyzerTool)、IDEA等,其他软件都需要将dump文件下载到本地分析,当dump文件很大的时候不方便,ma…

DCDC_LDO模块

DCDC/LDO模块 DC-DC 模块和 LDO(线性稳压器)模块是两种常用的电源管理解决方案。它们在电源转换和调节中各有特点和适用场景。以下是对这两种模块的详细介绍,包括它们的工作原理、优缺点、应用场景以及设计考虑。 一、DC-DC 模块 1. 工作原理 DC-DC 转换器通过高频开关元件(…

代码精简之路-模板模式

1. 前言 程序员怕重复CRUD,总是做一些简单繁琐的事情。“不要重复造轮子”,“把基础功能提炼出来封装成工具类” 我喜欢把这些话挂在嘴边,写起来常不知从何下手。 下面拆解一个项目中的功能。记录从复制粘贴到对业务抽象、实现功能分层的详细过程。如何着手提升代码重构优化…

覆铜宽度和电流大小之间的关系,掌握过孔大小与数量与电流大小的关系

覆铜宽度和电流大小之间的关系,掌握过孔大小与数量与电流大小的关系 在 PCB(印刷电路板)设计中,覆铜宽度和过孔的大小与电流处理能力之间的关系是非常重要的。这些因素直接影响到电路的安全性、性能和热管理能力。以下是关于覆铜宽度、电流大小、过孔大小与数量与电流之间关…

一字型布局L型布局的概念和器件摆放方法

一字型布局/L型布局的概念和器件摆放方法 在电子设计中,PCB(印刷电路板)的布局非常重要,而一字型布局和 L 型布局是常见的布局方法。这两种布局方式用于确保电路的稳定性、可制造性和性能。以下是对这两种布局的简要概述,以及器件摆放方法的说明。 一、一字型布局 概念: …

PCB模块

PCB模块 PCB(印刷电路板)模块是在电子设计和应用中非常常见的组件。它们是将电路功能集成到一个统一单元中的关键部分。下面,对 PCB 模块进行详细讲解,包括其定义、类型、应用和设计考虑等方面。 1. 什么是 PCB 模块? PCB 模块是指在印刷电路板上实现特定功能的预制电路板…

掌握一字型布局L型布局的概念和器件摆放方法

掌握一字型布局/L型布局的概念和器件摆放方法 在电子设计中,PCB(印刷电路板)的布局非常重要,而一字型布局和 L 型布局是常见的布局方法。这两种布局方式用于确保电路的稳定性、可制造性和性能。以下是对这两种布局的简要概述,以及器件摆放方法的说明。 一、一字型布局 概念…

掌握电源模块散热的处理

掌握电源模块散热的处理 电源模块的散热设计对于确保电子设备的性能和可靠性至关重要。由于电源模块在转换电能的过程中会产生热量,如果不合理处理散热,可能会导致模块过热,从而影响其工作效率、使用寿命,甚至导致系统故障。以下是电源模块散热处理的一些关键原则和方法: …

浅述中断机制

写在前面 本文重在讨论8086处理器的中断的原理与分类,以及一些中断向量表的内容。由于笔者水平有限,随笔中难免有些许纰漏和错误,希望广大读者能指正。 中断的分类 我们先来看看中断的分类。大体上来说,中断可以分为外部硬件中断、内部中断、软中断。 中断就是打断、暂停的…

浅述实模式下的中断

# 写在前面 本文重在讨论8086处理器的中断的原理与分类,以及一些中断向量表的内容。由于笔者水平有限,随笔中难免有些许纰漏和错误,希望广大读者能指正。 # 中断的分类 我们先来看看中断的分类。大体上来说,中断可以分为*外部硬件中断、内部中断、软中断。* 中断就是*打…