堆、栈、最小堆
堆是什么
结构属性
堆是一棵完全二叉树,即除最后一层外,其他层节点均填满,且最后一层节点从左到右连续分布。
排序属性:
根据类型不同,堆分为:
最大堆(Max-Heap) :每个节点的值大于或等于其子节点的值,根节点是堆中的最大值。
最小堆(Min-Heap) :每个节点的值小于或等于其子节点的值,根节点是堆中的最小值。
最小堆
特点
最小堆是堆的一种具体形式,其特点包括:
节点关系:任意父节点的值均小于或等于其左右子节点的值。根节点始终为堆中的最小元素。
存储方式:通常用数组实现,数组索引对应完全二叉树的层序遍历结果。例如,索引为i的节点,其父节点索引为(i-1)/2,左子节点为2i+1,右子节点为2i+2。
核心操作
插入元素:将新元素添加到数组末尾,再通过 上浮(Sift Up) 调整,即与父节点比较并交换,直至满足堆性质。时间复杂度为O(log n)。
删除根节点:移除根节点(即数组首元素)后,将末尾元素移至根位置,再通过 下沉(Sift Down) 调整,即与较小的子节点交换,直至满足堆性质。时间复杂度为O(log n)。
构建堆:从最后一个非叶子节点开始,依次向前调整每个子树为堆结构。时间复杂度为O(n)。
实现一个最小堆
class MinHeap {// 构造函数,初始化一个空数组来存储堆元素constructor() {this.heap = [];}// 获取父节点的索引getParentIndex(index) {return Math.floor((index - 1) / 2);}// 获取左子节点的索引getLeftChildIndex(index) {return index * 2 + 1;}// 获取右子节点的索引getRightChildIndex(index) {return index * 2 + 2;}// 向上调整堆,保持堆的性质up(index) {if (index === 0) return; // 如果已经是根节点,就不再调整const parentIndex = this.getParentIndex(index); // 获取父节点的索引// 如果当前节点小于父节点,交换两者if (this.heap[parentIndex] > this.heap[index]) {[this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];this.up(parentIndex); // 递归向上调整}}// 向下调整堆,保持堆的性质down(index) {const leftIndex = this.getLeftChildIndex(index); // 左子节点的索引const rightIndex = this.getRightChildIndex(index); // 右子节点的索引let smallest = index; // 假设当前节点最小// 如果左子节点存在且小于当前节点,更新最小值索引if (leftIndex < this.heap.length && this.heap[leftIndex] < this.heap[smallest]) {smallest = leftIndex;}// 如果右子节点存在且小于当前节点(或左子节点),更新最小值索引if (rightIndex < this.heap.length && this.heap[rightIndex] < this.heap[smallest]) {smallest = rightIndex;}// 如果最小值不是当前节点,交换并继续向下调整if (smallest !== index) {[this.heap[smallest], this.heap[index]] = [this.heap[index], this.heap[smallest]];this.down(smallest); // 递归向下调整}}// 查看堆顶元素(即最小值)peek() {return this.heap[0];}// 获取堆的大小(即堆中元素的个数)size() {return this.heap.length;}// 向堆中插入一个新元素insert(value) {this.heap.push(value); // 将新元素添加到堆的末尾this.up(this.heap.length - 1); // 调用向上调整方法保持堆的性质}// 移除堆顶元素(即最小值),并调整堆pop() {this.heap[0] = this.heap.pop(); // 将堆顶元素与堆末尾元素交换并移除堆顶this.down(0); // 调用向下调整方法保持堆的性质}}// 使用示例
let arr = new MinHeap();arr.insert(5); // 插入元素 5
arr.insert(4); // 插入元素 4
arr.insert(6); // 插入元素 6
arr.insert(1); // 插入元素 1// arr.pop(); // 移除堆顶元素(最小值)console.log(arr); // 输出当前堆的内容
console.log(arr.size()); // 输出堆的大小
console.log(arr.peek()); // 输出堆顶元素(最小值)
堆和栈的区别
1. 数据结构中的堆 vs 栈
| 特性 | 堆(Heap) | 栈(Stack) |
|---|---|---|
| 数据结构类型 | 完全二叉树(最大堆/最小堆) | 线性结构(LIFO:后进先出) |
| 核心操作 | 插入、删除极值元素(如最小堆的根节点) | 压栈(push)、弹栈(pop) |
| 时间复杂度 | 插入和删除为 O(log n) | 插入和删除为 O(1) |
| 典型应用 | 优先队列、堆排序、Top K 问题 | 函数调用栈、表达式求值、括号匹配 |
| 示例 | 任务调度中快速获取优先级最高的任务 | 递归调用时保存局部变量和返回地址 |
2. 内存管理中的堆 vs 栈
| 特性 | 堆(Heap) | 栈(Stack) |
|---|---|---|
| 内存分配方式 | 动态分配(程序员手动管理,如 malloc) | 自动分配(编译器管理,如局部变量) |
| 内存大小 | 较大,可动态扩展 | 较小,固定大小(可能溢出) |
| 生命周期 | 由程序员控制(需手动释放,否则内存泄漏) | 随函数调用自动创建和销毁 |
| 访问速度 | 较慢(需通过指针间接访问) | 极快(直接操作栈顶指针) |
| 碎片问题 | 可能存在内存碎片 | 无碎片 |
| 典型应用 | 存储动态数据(如对象、数组) | 存储函数参数、局部变量 |
关键区别总结
-
名称混淆:
- 数据结构中的“堆”是树形结构,而内存中的“堆”是动态内存区域,两者无直接关联。
- 数据结构中的“栈”是 LIFO 的线性结构,内存中的“栈”是函数调用的内存空间。
-
核心差异:
- 数据结构:堆用于高效管理极值元素,栈用于顺序操作(如撤销功能)。
- 内存管理:堆是灵活但需手动管理的动态内存,栈是高效但受限的自动内存。
-
易错点:
- 在 C/C++ 中,局部变量存储在栈上,函数返回后自动释放;堆内存需手动释放(
free/delete)。 - 栈溢出(Stack Overflow)是程序错误,堆内存泄漏(Memory Leak)是资源管理问题。
- 在 C/C++ 中,局部变量存储在栈上,函数返回后自动释放;堆内存需手动释放(
示例代码对比
// 内存中的栈 vs 堆
void example() {int a = 10; // 栈内存(自动分配)int *b = (int*)malloc(sizeof(int)); // 堆内存(手动分配)*b = 20;free(b); // 必须手动释放堆内存
}
应用场景
- 用栈的场景:
- 函数调用(保存上下文)。
- 实现撤销操作(如编辑器中的
Ctrl+Z)。
- 用堆的场景:
- 动态创建对象(如 Java/C++ 的
new)。 - 需要长期存在的数据(如全局缓存)。
- 动态创建对象(如 Java/C++ 的
相关文章:
堆、栈、最小堆
堆是什么 结构属性 堆是一棵完全二叉树,即除最后一层外,其他层节点均填满,且最后一层节点从左到右连续分布。 排序属性: 根据类型不同,堆分为: 最大堆(Max-Heap) :每…...
基于 Spring AI 的 HIS 系统智能化改造
【Spring AI 的背景与现状】 Spring AI 是 Spring 生态里整的一个新活儿,专门给开发者提供搞 AI 驱动的应用的工具和框架。虽然 Spring AI 已经鼓捣了挺长时间,但截至现在(2025年2月),它还没正式发布。不过࿰…...
React进阶之前端业务Hooks库(五)
前端业务Hooks库 Hooks原理useStateuseEffect上述问题useState,useEffect 复用的能力练习:怎样实现一套React过程中的hooks状态 & 副作用Hooks原理 不能在循环中、条件判断、子函数中调用,只能在函数最外层去调用useEffect 中,deps 为空,执行一次useState 使用: imp…...
常见锁类型介绍
下面结合代码详细介绍 Mutex、RW Lock、Futex、自旋锁、信号量、条件变量 和 synchronized,并分析它们的适用场景、特点以及为什么这些锁适用于特定场景。我们将从锁的实现机制和性能特点出发,解释其适用性。 1. Mutex(互斥锁) 代…...
Java中,Scanner和System.out超时的解决方法及原理
ACM 模式的原理 在输入输出的时候,会先将输入输出的东西放在一个文件里,这个文件也叫做 IO 设备 为什么 Scanner 会慢 new 一个 Scanner ,在 Scanner 里面调用 next 的时候,程序会直接访问 IO 设备。在调用一个 next 的时候&…...
一种数据高效具身操作的原子技能库构建方法
25年1月来自京东、中科大、深圳大学、海尔集团、地平线机器人和睿尔曼智能科技的论文“An Atomic Skill Library Construction Method for Data-Efficient Embodied Manipulation”。 具身操控是具身人工智能领域的一项基本能力。尽管目前的具身操控模型在特定场景下表现出一定…...
云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之新能源充电行业系统说明书
云创智城YunCharge 新能源充电行业系统说明书 ⚡官方文档 ⚡官网地址 1. 引言 随着全球环境保护和能源危机的加剧,新能源汽车行业得到了快速发展,充电基础设施建设也随之蓬勃发展。新能源充电行业系统旨在提供高效、便捷的充电服务,满足电…...
JVM垃圾回收器深度底层原理分析与知识体系构建
一、垃圾回收的基本步骤 标记(Marking) 从GC Roots(如虚拟机栈、方法区静态变量、本地方法栈等)出发,遍历对象引用链,标记所有可达对象为存活对象,未被标记的则视为垃圾。此阶段需暂停用户线程&…...
30.[前端开发-JavaScript基础]Day07-数组Array-高阶函数-日期Date-DOM
JavaScript的DOM操作 (一) 1 什么是DOM? 认识DOM和BOM 深入理解DOM 2 认识DOM Tree DOM Tree的理解 3 DOM的整体结构 DOM的学习顺序 DOM的继承关系图 document对象 4 节点、元素导航 节点(Node)之间的导航&…...
IP、网关、子网掩码、DNS 之间的关系详解
IP、网关、子网掩码、DNS 之间的关系详解 在计算机网络中,IP、网关、子网掩码和 DNS 是几个关键概念,它们协同工作,共同保障网络通信的顺畅。本文将详细探讨它们之间的关系。 一、IP 地址 IP 地址是网络中设备的唯一标识,如同现…...
【Day50 LeetCode】图论问题 Ⅷ
一、图论问题 Ⅷ 1、dijkstra算法 堆优化 采用堆来优化,适合节点多的稀疏图。代码如下: # include<iostream> # include<vector> # include<list> # include<queue> # include<climits>using namespace std;class myco…...
结构体介绍及内存大小分配问题
结构体 一.结构体的介绍1.1结构体的声明1.2匿名结构体1.3结构的自引用1.4使用 typedef 简化结构体类型名 二.结构体内存对齐2.1内存对齐规则2.2结构体内存对齐原因2.3修改默认对齐数 在 C 语言中,结构体(struct)是一种用户自定义的数据类型&a…...
halcon 条形码、二维码识别、opencv识别
一、条形码 函数介绍 create_bar_code_model * 1.创建条码读取器的模板 * 参数一:通用参数的名称,针对条形码模型进行调整。默认值为空 * 参数二:针对条形码模型进行调整 * 参数三:条形码模型的句柄。 create_bar_code_model (…...
Vue框架的使用 搭建打包 Vue的安全问题(Xss,源码泄露)
前言 什么是Vue? Vue是轻量级的js框架 可以帮助我们一键构造网站,打包app程序等 Vue的基本使用 1、构造框架并启用 新建一个 目录 使用终端切换到当前的目录 创建vue项目 第一个弹出使用语法我们选择是 剩下的全选择否 发现创建好了 接着进行…...
Java+SpringBoot+Vue+数据可视化的音乐推荐与可视化平台(程序+论文+讲解+安装+调试+售后)
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,我会一一回复,希望帮助更多的人。 系统介绍 在互联网技术以日新月异之势迅猛发展的浪潮下,5G 通信技术的普及、云计算能力…...
day2 - SpringBoot框架开发技术
主要内容 1. SpringBoot简介 2. 构建springboot工程 3. springboot接口返回json 4. springboot热部署 5. springboot资源属性配置 6. springboot整合模板引擎 7. springboot异常处理 8. springboot整合MyBatis 9. springboot整合redis 10. springboot整合定时任务 11. springbo…...
Flash-03
1-问题:Flash软件画两个图形,若有部分重合则变为一个整体 解决方法1:两个图形分属于不同的图层 解决方法2:将每个图形都转化为【元件】 问题2:元件是什么? 在 Adobe Flash(现在称为 Adobe Anim…...
新建菜单项的创建之CmpGetValueListFromCache函数分析
第一部分: PCELL_DATA CmpGetValueListFromCache( IN PHHIVE Hive, IN PCACHED_CHILD_LIST ChildList, OUT BOOLEAN *IndexCached, OUT PHCELL_INDEX ValueListToRelease ) 0: kd> dv KeyControlBlock 0xe1…...
【Word2Vec】Skip-gram 的直观理解(深入浅出)
01 什么是skip-gram 一句话来说就是,给定中心词,然后预测其周围的词: 02 模型结构 对于skip-gram来说,输入是一个[1 x V]维的ont-hot向量,其中V为词表大小,值为1的那一项就表示我们的中心词。经过一个[V x…...
在MacOS上打造本地部署的大模型知识库(一)
一、在MacOS上安装Ollama docker run -d -p 3000:8080 --add-hosthost.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main 最后停掉Docker的ollama,就能在webui中加载llama模…...
用LLM提高语音转文本的准确率
语音转文本转换,也称为自动语音识别(ASR)或音频转录,是将口语音频转换为书面文本的过程,生成的文本称为转录稿。虽然基于 Transformer 的模型现已广泛应用于语音转文本转换,但对于较小或资源匮乏的语言&…...
Shell 脚本:别让你的自动化变成“自爆化”
太长不看版(老鸟)脚本头:#!/bin/bash 写死,别用 #!/bin/sh(坑太多)。调试:bash -x script.sh 能看到每一行执行过程。变量引用:永远用双引号包起来 "$var",否则…...
WebStorm高效开发Vue3+TypeScript项目:配置与实战技巧
1. WebStorm与Vue3TypeScript开发环境搭建 WebStorm作为JetBrains旗下的前端开发利器,对Vue3和TypeScript的支持堪称完美。最新版本甚至内置了Volar语言服务,让类型推断和代码补全更加精准。先说说我的踩坑经历:第一次用WebStorm创建Vue3项目…...
.NET后端集成:开发Windows桌面端字幕制作工具
.NET后端集成:开发Windows桌面端字幕制作工具 1. 引言 做视频的朋友们,尤其是那些需要处理大量口播、课程或者访谈内容的,应该都体会过手动加字幕的“痛苦”。一句一句听,一帧一帧对,眼睛盯着波形图,手指…...
大型欧姆龙PLC NJ系列ST语言Ethercat总线24轴 伺服电池生产线欧姆龙PLC程序大...
大型欧姆龙PLC NJ系列ST语言Ethercat总线24轴 伺服电池生产线欧姆龙PLC程序大型程序NJ系列 ST语言EtherCat总 线控制24个伺服轴大型程序电池生产线 包括PLC NJ-1400和威纶通触摸屏程序 PLC通过EtherCat总线连接24个IS620N伺服 伺服轴已经写好FB块,可以直接复制粘贴 …...
linux-内核结构体
vma结构体定义在include/linux/mm_types.h中。 每一段(比如代码段、堆、栈)都由一个vma结构体来描述。 它记录了这段内存的起止地址、权限(读写执行)以及背后的存储介质(是匿名内存还是映射了文件)。 权限隔…...
掌握AI教材写作,借助低查重方法打造优质专业教材!
教材创作难题与AI解决方案 很多教材编写者都会遇到一个共同的问题:虽然他们的正文内容经过了精细的打磨,但由于配套资源的缺乏,整体教学效果受到影响。设计不同层次的课后练习往往需要新颖的点子,而很多时候这些灵感难以涌现&…...
Ollama上的轻量神器:Granite-4.0-H-350M快速部署与效果评测
Ollama上的轻量神器:Granite-4.0-H-350M快速部署与效果评测 1. 模型概述:轻量级多语言指令模型 Granite-4.0-H-350M是IBM推出的轻量级指令模型,专为边缘计算和本地部署场景优化。该模型基于Granite-4.0-H-350M-Base版本,通过有监…...
告别if-else地狱!在Godot 4.4里用状态机重构你的2D角色控制器
告别if-else地狱!在Godot 4.4里用状态机重构你的2D角色控制器 当你的2D平台游戏角色开始拥有跑跳、攻击、滑铲等复杂动作时,脚本里层层嵌套的if-else判断会像野草般疯长。上周我接手一个项目,发现玩家控制器脚本竟有200多行条件判断——添加新…...
OpenClaw投资分析:Qwen3.5-9B处理财经新闻与报表摘要
OpenClaw投资分析:Qwen3.5-9B处理财经新闻与报表摘要 1. 为什么选择本地化金融数据处理方案 去年我在尝试搭建个人投资分析系统时,遇到了一个典型困境:既需要大模型处理海量财经信息,又担心将敏感财务数据上传到公有云的风险。经…...
