数据结构之堆:原理与实现

1. 什么是堆?

堆(Heap)是一种特殊的完全二叉树,它的每个节点都遵循以下性质之一:

  • 最大堆(Max-Heap):每个节点的值都大于等于其子节点的值,根节点是最大值。
  • 最小堆(Min-Heap):每个节点的值都小于等于其子节点的值,根节点是最小值。

堆的主要特点是便于快速获取最大值最小值,因此堆广泛用于优先队列堆排序等场景。

2. 堆的存储结构

堆通常用数组存储,其逻辑结构是树形,但存储方式是顺序存储(数组)。堆节点的索引关系如下:

  • 父节点:索引为i的节点的父节点在索引(i-1)/2
  • 左子节点:索引为i的节点的左子节点在索引2*i+1
  • 右子节点:索引为i的节点的右子节点在索引2*i+2

堆的数组表示示例: 对于完全二叉树:

​10/    \9        8/ \      / \7   6    5   4
​

对应的数组存储为:[10, 9, 8, 7, 6, 5, 4]

3. 堆的操作

堆的核心操作包括:

  1. 插入(Insert):在堆中添加新元素,并维护堆的性质。
  2. 删除(Delete):从堆中移除根节点(最大堆中的最大值或最小堆中的最小值),并维护堆的性质。
  3. 堆化(Heapify):调整堆以恢复堆性质,分为向上调整向下调整

其中向下调整如图:

4. 堆的实现

以下是用C语言实现最大堆的代码示例:

1. 堆的定义和初始化
​
#include <stdio.h>
#include <stdlib.h>typedef struct {int *data;     // 数组存储堆的元素int size;      // 当前堆中元素数量int capacity;  // 堆的容量
} Heap;// 初始化堆
Heap* createHeap(int capacity) {Heap* heap = (Heap*)malloc(sizeof(Heap));heap->data = (int*)malloc(sizeof(int) * capacity);heap->size = 0;heap->capacity = capacity;return heap;
}​

2. 插入操作(Insert)

插入新元素时,需要将元素放到堆的最后,然后通过向上调整恢复堆的性质。

​
void insert(Heap* heap, int value) {if (heap->size >= heap->capacity) {printf("堆已满,无法插入元素。\n");return;}heap->data[heap->size] = value;  // 将新元素放在堆的末尾int i = heap->size;heap->size++;// 向上调整while (i > 0 && heap->data[i] > heap->data[(i-1)/2]) {// 如果当前节点大于父节点,交换两者int temp = heap->data[i];heap->data[i] = heap->data[(i-1)/2];heap->data[(i-1)/2] = temp;i = (i-1)/2;  // 更新当前节点为父节点}
}​

3. 删除操作(Delete)

删除最大堆中的根节点(即最大值)时,需要将堆的最后一个元素放到根节点位置,并通过向下调整恢复堆的性质。

​
int deleteMax(Heap* heap) {if (heap->size <= 0) {printf("堆为空,无法删除元素。\n");return -1;}int maxValue = heap->data[0];  // 根节点的值即为最大值heap->data[0] = heap->data[heap->size - 1]; // 用最后一个元素替换根节点heap->size--;int i = 0;while (2*i+1 < heap->size) {  // 检查是否有左子节点int maxChild = 2*i+1;  // 假设左子节点为较大子节点if (2*i+2 < heap->size && heap->data[2*i+2] > heap->data[2*i+1]) {maxChild = 2*i+2;  // 如果右子节点更大,则更新为右子节点}if (heap->data[i] >= heap->data[maxChild]) {break;  // 如果当前节点大于等于较大子节点,堆已调整完毕}// 交换当前节点和较大子节点int temp = heap->data[i];heap->data[i] = heap->data[maxChild];heap->data[maxChild] = temp;i = maxChild;  // 更新当前节点为较大子节点}return maxValue;
}​

4. 打印堆内容
​
void printHeap(Heap* heap) {for (int i = 0; i < heap->size; i++) {printf("%d ", heap->data[i]);}printf("\n");
}​

5. 测试堆的操作
​
int main() {Heap* heap = createHeap(10);insert(heap, 15);insert(heap, 10);insert(heap, 30);insert(heap, 25);printf("当前堆: ");printHeap(heap);printf("删除最大值: %d\n", deleteMax(heap));printf("当前堆: ");printHeap(heap);free(heap->data);free(heap);return 0;
}​

5. 堆的应用场景
  1. 优先队列:基于堆实现的优先队列可以快速获取优先级最高的元素。
  2. 堆排序:堆是一种高效的排序工具,时间复杂度为O(n log n)
  3. 图算法:在Dijkstra最短路径算法和Prim最小生成树算法中,堆用于高效选择最小权重边。
  4. Top K问题:用最小堆快速找到一组数据中的前K大元素。

6. 堆的优缺点
特性优点缺点
存储方式数组存储,结构紧凑动态扩展时需要重新分配内存
操作效率插入和删除的时间复杂度为O(log n)查找特定元素需要遍历整个堆,时间复杂度为O(n)
实现复杂度算法简单,易于实现对于大数据场景,调整操作可能有一定性能开销

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

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

相关文章

DreamCamera2相机预览变形的处理

最近遇到一个问题&#xff0c;相机更换了摄像头后&#xff0c;发现人像角度顺时针旋转了90度&#xff0c;待人像角度正常后&#xff0c;发现 预览时图像有挤压变形&#xff0c;最终解决。在此记录 一人像角度的修改 先放示意图 设备预览人像角度如图1所示&#xff0c;顺时针旋…

GPT相关的学术库——收藏更新自用

GOT-OCR2.0 General OCR Theory: Towards OCR-2.0 via a Unified End-to-end Model https://github.com/Ucas-HaoranWei/GOT-OCR2.0/tree/main ChatPaper 工具名称工具作用是否在线&#xff1f;在线预览备注ChatPaper通过ChatGPT实现对论文进行总结&#xff0c;帮助科研人进…

LLM之学习笔记(一)

前言 记录一下自己的学习历程&#xff0c;也怕自己忘掉了某些知识点 Prefix LM 和 Causal LM区别是什么&#xff1f; Prefix LM &#xff08;前缀语⾔模型&#xff09;和 Causal LM&#xff08;因果语言模型&#xff09;是两者不同类型的语言模型&#xff0c;它们的区别在于生…

Python语法基础(三)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们这篇文章来说一下函数的返回值和匿名函数 函数的返回值 我们先来看下面的这一段函数的定义代码 # 1、返回值的意义 def func1():print(111111111------start)num166print…

用Pycharm安装manim

由于版本和工具的差异&#xff0c;manim的安装方式不尽相同。本文用Pycharm来安装manim. 一、准备工作&#xff1a;安装相应版本的python、pycharm和ffmpeg. 此处提供一种安装ffmpeg的方式 下载地址&#xff1a;FFmpeg 下载后&#xff0c;解压到指定目录。 配置环境变量&am…

【线程】Java多线程代码案例(2)

【线程】Java多线程代码案例&#xff08;2&#xff09; 一、定时器的实现1.1Java标准库定时器1.2 定时器的实现 二、线程池的实现2.1 线程池2.2 Java标准库中的线程池2.3 线程池的实现 一、定时器的实现 1.1Java标准库定时器 import java.util.Timer; import java.util.Timer…

云原生时代的轻量级反向代理Traefik

Traefik 是一个用于路由和管理网络流量的反向代理&#xff0c;同时也是一个支持多种协议&#xff08;HTTP、HTTPS、TCP、UDP&#xff09;的负载均衡器。它通过自动服务发现和动态配置&#xff0c;帮助开发者和运维团队轻松管理复杂的应用架构。 Traefik 的主要特点如下&#x…

JavaEE---计算机是如何工作的?

1.了解冯诺依曼体系结构 2.CPU的核心概念,CPU的两个重要指标(核心数和频率) 3.CPU执行指令的流程(指令表,一条一条指令,取指令,解析指令,执行指令) 4.操作系统核心概念(管理硬件,给软件提供稳定的运行环境) 5.进程的概念(运行起来的程序和可执行文件的区别) 6.进程的管理(…

【C++】简单数据类型详解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;字符型&#xff08;char&#xff09;1.1 ASCII 码表 &#x1f4af;整型&#xff08;int&#xff09;2.1 整型的分类2.2 有符号和无符号整型2.3 跨平台差异2.4 整型数据类型…

Vue构建错误解决:(error TS6133)xxx is declared but its value is never read.

TypeScript会检查代码中未使用的变量&#xff0c;如果vscode安装了Vue的语法检查工具&#xff0c;会看到告警提示&#xff0c;再npm run build的时候&#xff0c;这个警告会变成错误 解决方案1&#xff1a;删除定义了未使用的变量 推荐使用这种方案&#xff0c;能保证代码的质…

泷羽sec---shell作业

作业一 写计算器 使用bc命令 需要进行安装bc 代码如下&#xff1a; #!/bin/bash echo "-----------------------------------" echo "输入 f 退出" echo "可计算小数和整数" echo "用法如&#xff1a;1.12.2" echo "------…

混淆零碎知识点

minifyEnabled true //混淆开关 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 &#xff08;必须要混淆开了之后才才可以设置为true&#xff09; proguard-rules.pro 为混淆文件 //整个文件保留 不被混淆 -keep class com.cn…

DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly Detection

DeSTSeg: Segmentation Guided Denoising Student-Teacher for Anomaly Detection 清华、苹果 个人感觉 Introduction 很自然的让读者理解作者问题的提出&#xff0c;也有例子直接证明了这个问题的存在&#xff0c;值得借鉴&#xff01;&#xff01; Related work写的也很不…

第T9周:Tensorflow实现猫狗识别(2)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: Tensorflow 2.10.0 &#xff08;二&#xff09;具体…

分布式锁的实现原理

作者&#xff1a;来自 vivo 互联网服务器团队- Xu Yaoming 介绍分布式锁的实现原理。 一、分布式锁概述 分布式锁&#xff0c;顾名思义&#xff0c;就是在分布式环境下使用的锁。众所周知&#xff0c;在并发编程中&#xff0c;我们经常需要借助并发控制工具&#xff0c;如 mu…

搭建帮助中心到底有什么作用?

在当今快节奏的商业环境中&#xff0c;企业面临着日益增长的客户需求和竞争压力。搭建一个有效的帮助中心对于企业来说&#xff0c;不仅是提升客户服务体验的重要途径&#xff0c;也是优化内部知识管理和提升团队效率的关键。以下是帮助中心在企业运营中的几个关键作用&#xf…

深入浅出剖析典型文生图产品Midjourney

2022年7月,一个小团队推出了公测的 Midjourney,打破了 AIGC 领域的大厂垄断。作为一个精调生成模型,以聊天机器人方式部署在 Discord,它创作的《太空歌剧院》作品,甚至获得了美国「数字艺术/数码摄影」竞赛单元一等奖。 这一事件展示了 AI 在绘画领域惊人的创造力,让人们…

python+docx:(二)页眉页脚、表格操作

目录 页眉页脚 表格 表格样式 插入表格 插入行/列 合并单元格 单元格 页眉页脚 页眉页脚操作需要访问文件的section&#xff0c;可通过添加页脚来添加页码。 from docx import Document from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_ALIGN_PARAGRAPH, WD_CO…

Matlab Simulink 电力电子仿真-单相电压型半桥逆变电路分析

目录 一、单相电压型半桥逆变电路仿真模型 1.电路模型 2.电路模型参数 二、仿真分析 三、总结 1.优缺点 2.应用场景 一、单相电压型半桥逆变电路仿真模型 1.电路模型 单相电压型半桥逆变电路是一种常见的逆变电路&#xff0c;主要用于将直流电源转换为交流电源。 &…

C++入门——“C++11-lambda”

引入 C11支持lambda表达式&#xff0c;lambda是一个匿名函数对象&#xff0c;它允许在函数体中直接定义。 一、初识lambda lambda的结构是&#xff1a;[ ] () -> 返回值类型 { }。从左到右依次是&#xff1a;捕捉列表 函数参数 -> 返回值类型 函数体。 以下是一段用lam…