当前位置: 首页 > news >正文

堆、栈、最小堆

堆是什么

结构属性

堆是一棵完全二叉树,即除最后一层外,其他层节点均填满,且最后一层节点从左到右连续分布。

排序属性:

根据类型不同,堆分为:
最大堆(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自动分配(编译器管理,如局部变量)
内存大小较大,可动态扩展较小,固定大小(可能溢出)
生命周期由程序员控制(需手动释放,否则内存泄漏)随函数调用自动创建和销毁
访问速度较慢(需通过指针间接访问)极快(直接操作栈顶指针)
碎片问题可能存在内存碎片无碎片
典型应用存储动态数据(如对象、数组)存储函数参数、局部变量

关键区别总结

  1. 名称混淆

    • 数据结构中的“堆”是树形结构,而内存中的“堆”是动态内存区域,两者无直接关联。
    • 数据结构中的“栈”是 LIFO 的线性结构,内存中的“栈”是函数调用的内存空间。
  2. 核心差异

    • 数据结构:堆用于高效管理极值元素,栈用于顺序操作(如撤销功能)。
    • 内存管理:堆是灵活但需手动管理的动态内存,栈是高效但受限的自动内存。
  3. 易错点

    • 在 C/C++ 中,局部变量存储在栈上,函数返回后自动释放;堆内存需手动释放(free/delete)。
    • 栈溢出(Stack Overflow)是程序错误,堆内存泄漏(Memory Leak)是资源管理问题。

示例代码对比

// 内存中的栈 vs 堆
void example() {int a = 10;          // 栈内存(自动分配)int *b = (int*)malloc(sizeof(int));  // 堆内存(手动分配)*b = 20;free(b);             // 必须手动释放堆内存
}

应用场景

  • 用栈的场景
    • 函数调用(保存上下文)。
    • 实现撤销操作(如编辑器中的 Ctrl+Z)。
  • 用堆的场景
    • 动态创建对象(如 Java/C++ 的 new)。
    • 需要长期存在的数据(如全局缓存)。

相关文章:

堆、栈、最小堆

堆是什么 结构属性 堆是一棵完全二叉树&#xff0c;即除最后一层外&#xff0c;其他层节点均填满&#xff0c;且最后一层节点从左到右连续分布。 排序属性&#xff1a; 根据类型不同&#xff0c;堆分为&#xff1a; 最大堆&#xff08;Max-Heap&#xff09; &#xff1a;每…...

基于 Spring AI 的 HIS 系统智能化改造

【Spring AI 的背景与现状】 Spring AI 是 Spring 生态里整的一个新活儿&#xff0c;专门给开发者提供搞 AI 驱动的应用的工具和框架。虽然 Spring AI 已经鼓捣了挺长时间&#xff0c;但截至现在&#xff08;2025年2月&#xff09;&#xff0c;它还没正式发布。不过&#xff0…...

React进阶之前端业务Hooks库(五)

前端业务Hooks库 Hooks原理useStateuseEffect上述问题useState,useEffect 复用的能力练习:怎样实现一套React过程中的hooks状态 & 副作用Hooks原理 不能在循环中、条件判断、子函数中调用,只能在函数最外层去调用useEffect 中,deps 为空,执行一次useState 使用: imp…...

常见锁类型介绍

下面结合代码详细介绍 Mutex、RW Lock、Futex、自旋锁、信号量、条件变量 和 synchronized&#xff0c;并分析它们的适用场景、特点以及为什么这些锁适用于特定场景。我们将从锁的实现机制和性能特点出发&#xff0c;解释其适用性。 1. Mutex&#xff08;互斥锁&#xff09; 代…...

Java中,Scanner和System.out超时的解决方法及原理

ACM 模式的原理 在输入输出的时候&#xff0c;会先将输入输出的东西放在一个文件里&#xff0c;这个文件也叫做 IO 设备 为什么 Scanner 会慢 new 一个 Scanner &#xff0c;在 Scanner 里面调用 next 的时候&#xff0c;程序会直接访问 IO 设备。在调用一个 next 的时候&…...

一种数据高效具身操作的原子技能库构建方法

25年1月来自京东、中科大、深圳大学、海尔集团、地平线机器人和睿尔曼智能科技的论文“An Atomic Skill Library Construction Method for Data-Efficient Embodied Manipulation”。 具身操控是具身人工智能领域的一项基本能力。尽管目前的具身操控模型在特定场景下表现出一定…...

云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之新能源充电行业系统说明书

云创智城YunCharge 新能源充电行业系统说明书 ⚡官方文档 ⚡官网地址 1. 引言 随着全球环境保护和能源危机的加剧&#xff0c;新能源汽车行业得到了快速发展&#xff0c;充电基础设施建设也随之蓬勃发展。新能源充电行业系统旨在提供高效、便捷的充电服务&#xff0c;满足电…...

JVM垃圾回收器深度底层原理分析与知识体系构建

一、垃圾回收的基本步骤 标记&#xff08;Marking&#xff09; 从GC Roots&#xff08;如虚拟机栈、方法区静态变量、本地方法栈等&#xff09;出发&#xff0c;遍历对象引用链&#xff0c;标记所有可达对象为存活对象&#xff0c;未被标记的则视为垃圾。此阶段需暂停用户线程&…...

30.[前端开发-JavaScript基础]Day07-数组Array-高阶函数-日期Date-DOM

JavaScript的DOM操作 &#xff08;一&#xff09; 1 什么是DOM&#xff1f; 认识DOM和BOM 深入理解DOM 2 认识DOM Tree DOM Tree的理解 3 DOM的整体结构 DOM的学习顺序 DOM的继承关系图 document对象 4 节点、元素导航 节点&#xff08;Node&#xff09;之间的导航&…...

IP、网关、子网掩码、DNS 之间的关系详解

IP、网关、子网掩码、DNS 之间的关系详解 在计算机网络中&#xff0c;IP、网关、子网掩码和 DNS 是几个关键概念&#xff0c;它们协同工作&#xff0c;共同保障网络通信的顺畅。本文将详细探讨它们之间的关系。 一、IP 地址 IP 地址是网络中设备的唯一标识&#xff0c;如同现…...

【Day50 LeetCode】图论问题 Ⅷ

一、图论问题 Ⅷ 1、dijkstra算法 堆优化 采用堆来优化&#xff0c;适合节点多的稀疏图。代码如下&#xff1a; # 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 语言中&#xff0c;结构体&#xff08;struct&#xff09;是一种用户自定义的数据类型&a…...

halcon 条形码、二维码识别、opencv识别

一、条形码 函数介绍 create_bar_code_model * 1.创建条码读取器的模板 * 参数一&#xff1a;通用参数的名称&#xff0c;针对条形码模型进行调整。默认值为空 * 参数二&#xff1a;针对条形码模型进行调整 * 参数三&#xff1a;条形码模型的句柄。 create_bar_code_model (…...

Vue框架的使用 搭建打包 Vue的安全问题(Xss,源码泄露)

前言 什么是Vue&#xff1f; Vue是轻量级的js框架 可以帮助我们一键构造网站&#xff0c;打包app程序等 Vue的基本使用 1、构造框架并启用 新建一个 目录 使用终端切换到当前的目录 创建vue项目 第一个弹出使用语法我们选择是 剩下的全选择否 发现创建好了 接着进行…...

Java+SpringBoot+Vue+数据可视化的音乐推荐与可视化平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在互联网技术以日新月异之势迅猛发展的浪潮下&#xff0c;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-问题&#xff1a;Flash软件画两个图形&#xff0c;若有部分重合则变为一个整体 解决方法1&#xff1a;两个图形分属于不同的图层 解决方法2&#xff1a;将每个图形都转化为【元件】 问题2&#xff1a;元件是什么&#xff1f; 在 Adobe Flash&#xff08;现在称为 Adobe Anim…...

新建菜单项的创建之CmpGetValueListFromCache函数分析

第一部分&#xff1a; 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 一句话来说就是&#xff0c;给定中心词&#xff0c;然后预测其周围的词&#xff1a; 02 模型结构 对于skip-gram来说&#xff0c;输入是一个[1 x V]维的ont-hot向量&#xff0c;其中V为词表大小&#xff0c;值为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&#xff0c;就能在webui中加载llama模…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...