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

堆的实现(偷懒版)

                           🌹个人主页🌹:喜欢草莓熊的bear

                           🌹专栏🌹:数据结构


目录

前言

一、堆的实现

1.1 堆的向下调整算法

思路:

1.2 堆的向上调整算法

1.3 堆的创建

1.4 堆的复杂度计算

向下调整建堆的复杂度:

  向上调整建堆的复杂度:

1.5 堆的插入

1.6 堆的删除

1.7 堆的代码实现

总结


前言

在上期内容介绍了二叉树、还简单提了一下堆的概念和大堆、小堆。回顾一下堆是首先是完全二叉树,因为是完全二叉树所以使用数组储存比较合理。

一、堆的实现

1.1 堆的向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。
给上一个例子
int arr[] = {27,15,19,18,28,34,65,49,25,37};

 上面这幅图就是向下调整的算法的过程图

思路:

 假设我们通过向下调整算法建立小堆,我们就需要从根的左右子树开始,比较得出左右子树小的那一个和根比较,谁小谁就是根。我们之前还介绍父亲节点和孩子节点的概念,我们这里就要使用到。根据我们上面的思路,向下调整算法需要通过比较还在节点后进行调整。所以我们需要知道父亲节点然后再找到孩子节点为什么要知道父亲节点呢?我们通过数组储存着堆,下标就可以帮助我们找到孩子节点。

 大致思路就是这样我们来写代码:

void Swap(HPDataType* x, HPDataType* y)//交换数据
{HPDataType tmp = *x;*x = *y;*y = tmp;
}void ADjustDown(HPDataType* a, int n,int parent)//向下调整
{int child = parent * 2 + 1;while (child < n){//假设法if (a[child] > a[child + 1] && child + 1 < n)//比较左右子树,找到较小的子树。{child++;}if (a[parent] > a[child])//数据交换{Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

 解释一下个别代码,child + 1  < n 防止数组越界。 

1.2 堆的向上调整算法

 向上调整我们需要从最后一层向上调整,所以我们是通过孩子节点得到父亲节点。大致思路和向下调整一样,比较孩子节点的大小后再和父亲节点比较一直比较到根节点。根据child = parent *2+1 反推得到 parent = ( child -1 )/2 。

直接上代码:

void Swap(HPDataType* x, HPDataType* y)//交换数据
{HPDataType tmp = *x;*x = *y;*y = tmp;
}void ADjustUp(HPDataType* a,int child)//向上调整
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent= (child - 1) / 2;}else{break;}}
}

1.3 堆的创建

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。
给上一个例子:
int a[] = {1,5,3,8,7,6};

1.4 堆的复杂度计算

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明 ( 时间复杂度本来看的就是近似值,多几个节点不影响最终结果)

向下调整建堆的复杂度:

  向上调整建堆的复杂度:

是O(N) = N * logN 得到方法和向下调整一样推导就可以了。

1.5 堆的插入

先插入一个 10 到数组的尾上,再进行向上调整算法,直到满足堆。

 堆的插入需要用的向上调整

1.6 堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。

 

1.7 堆的代码实现

堆的初始化、销毁都是很简单和之前写的栈啊等等都十分相似。剩下一些 获取堆顶元素、堆的个数、堆的判断都比较简单就不讲解了给上了代码。

typedef int HPDataType;typedef struct Heap//因为堆的定义就是满二叉树与完全二叉树,用数组储存非常好。
{HPDataType* a;//数组int size;int capacity;
}Heap;//小堆情况下的初始化
void HPInit(Heap* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}//销毁
void HPDestory(Heap* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;
}void Swap(HPDataType* x, HPDataType* y)//交换数据
{HPDataType tmp = *x;*x = *y;*y = tmp;
}void ADjustUp(HPDataType* a,int child)//向上调整
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent= (child - 1) / 2;}else{break;}}
}void ADjustDown(HPDataType* a, int n,int parent)//向下调整
{int child = parent * 2 + 1;while (child < n){//假设法if (a[child] > a[child + 1] && child + 1 < n){child++;}if (a[parent] > a[child]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}//入堆
void HPPush(Heap* php, HPDataType x)
{assert(php);//扩容if (php->size == php->capacity){int Newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a, Newcapacity * sizeof(HPDataType));if (tmp == NULL){perror("ralloc fail");return;}php->a = tmp;php->capacity = Newcapacity;}php->a[php->size++] = x; ADjustUp(php->a,php->size - 1);
}//出堆(消除堆顶数据)
void HPPop(Heap* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;ADjustDown(php->a,php->size,0);
}//取堆顶数据
HPDataType HPTop(Heap* php)
{assert(php);assert(php->size > 0);return php->a[0];
}//堆的数据个数
int HPSize(Heap* php)
{assert(php);return php->size;
}//堆的判空
bool HPEmpty(Heap* php)
{assert(php);return php->size == 0;
}

总结

本节重点堆的向上、向下调整算法的代码实现 和 复杂度计算。

相关文章:

堆的实现(偷懒版)

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 目录 前言 一、堆的实现 1.1 堆的向下调整算法 思路&#xff1a; 1.2 堆的向上调整算法 1.3 堆的创建 1.4 堆的复杂度计算 向下调整建堆的复杂度…...

一键启动,智能分拣:3D视觉系统赋能多SKU纸箱高效混拆作业

在快速发展的电商时代&#xff0c;仓储物流面临着前所未有的挑战。尤其是面对成千上万种不同的纸箱&#xff0c;如何实现快速、准确、高效的混拆作业&#xff0c;成为了众多企业亟待解决的问题。幸运的是&#xff0c;随着科技的进步&#xff0c;3D视觉系统正逐步成为这一领域的…...

unity草体渲染方案 GPU Instaning

有一天看项目里的FrameDebug发现在森林系的场景里草体的drawcall差不多有100多 主要是因为灯光贴图&#xff0c;位置等不一样导致的打断合批&#xff0c;导致一个批次只能渲染10个左右的草体 之前有了解过unity有接口&#xff08;Graphics.DrawMeshInstanced&#xff09;可以把…...

最近在西安召开的学术会议:EI检索超快,信息系统与计算技术领域!

第十二届信息系统与计算技术国际会议&#xff08;ISCTech 2024&#xff09;将于2024年11月8日-11月11日在中国西安盛大举行&#xff0c;由长沙理工大学主办&#xff0c;同济大学、西北工业大学联合协办。会议聚焦信息系统与计算技术等相关研究领域&#xff0c;广泛邀请国内外知…...

sRGB和伽马矫正

sRGB和伽马矫正 1. sRGB的含义&#xff1a; sRGB是一种色彩空间&#xff0c;全称为“标准红色-绿色-蓝色”&#xff08;standard Red Green Blue&#xff09;。它由惠普和微软在1996年共同开发&#xff0c;用于确保不同设备上色彩的一致性。 在sRGB中&#xff0c;“s”代表“…...

Summer School science communication project--Laptop Selection Suggestion

目录 Introduction Audiance Usage CPU What is a central processing unit (CPU) Notable makers of CPUs GPU Graphics Card: GPU The classifications of graphics cards The brands of graphics cards Dedicated Graphics Cards GeForce MX Series: GeForc…...

网络编程概念详解模拟回显客户端服务器

目录 1.网络中重要的概念 1&#xff09;IP地址&#xff1a; 2&#xff09;端口号&#xff1a; 3&#xff09;协议 协议分层 OSI七层模型(教科书) TCP/IP五层模型 封装和分用 网络套接字 面试题&#xff1a;TCP/UDP的区别&#xff1f; UDP数据报套接字编程 模拟一个回…...

代码随想录第二十四天|动态规划(8)

目录 LeetCode 300. 最长递增子序列 LeetCode 674. 最长连续递增序列 LeetCode 718. 最长重复子数组 LeetCode 1143. 最长公共子序列 LeetCode 1035. 不相交的钱 LeetCode 53. 最大子序和 LeetCode 392. 判断子序列 总结 LeetCode 300. 最长递增子序列 题目链接&#…...

编程-设计模式 3:单例模式

设计模式 3&#xff1a;单例模式 定义与目的 定义&#xff1a;单例模式确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。目的&#xff1a;这种模式通常用于那些需要频繁访问且只需一个实例的对象&#xff0c;例如配置管理器、日志记录器等。 实现示例…...

Kaniko 构建 Docker 镜像

Kaniko 主要用于构建 Docker 镜像&#xff0c;而不是运行程序。它的主要用途是从 Dockerfile 构建容器镜像&#xff0c;但它并不负责运行容器或程序。以下是 Kaniko 的主要功能和局限性&#xff1a; 主要功能 构建镜像&#xff1a;Kaniko 从 Dockerfile 构建容器镜像。它通过…...

Javascript常见算法(每日两个)

合并两个有序链表 在JavaScript中&#xff0c;合并两个有序链表通常指的是将两个已经按照某种顺序&#xff08;如升序或降序&#xff09;排列的链表合并成一个新的有序链表。由于JavaScript本身不直接支持链表数据结构&#xff0c;我们通常会用对象或数组来模拟链表的行为。但…...

Spring -- 事务

Spring中事务的操作分为两类:(1)编程式事务 – 手动写代码操作事务(2)声明式事务 – 利用注解开启事务和提交事务 1. 编程式事务 准备Controller RestController RequestMapping("/user") public class UserInfoController {Autowiredprivate UserInfoService use…...

生命密码的破译者:AI如何学会读懂DNA语言?

引言 如果能像解读一本神秘的书籍那样&#xff0c;理解DNA的“语言”&#xff0c;将是多么令人兴奋的科学突破&#xff01;如今&#xff0c;这正在逐步变为现实。科学家们训练出的AI模型GROVER正如一个勤奋的学生&#xff0c;学习着DNA的每一个“单词”和“语法”&#xff0c;…...

大数据信用报告查询哪家平台的比较好?

相信在搜索大数据信用的你&#xff0c;已经因为大数据信用不好受到了挫折&#xff0c;想详细了解一下自己的大数据信用&#xff0c;但是找遍了网络上的平台之后才发现&#xff0c;很多平台都只提供查询服务&#xff0c;想要找一个专业的平台查询和讲解很困难。下面本文就为大家…...

Java高级Day24-集合最后补充

75.HashTable 基本介绍&#xff1a; 存放元素的健值对 即K-V hashtable的键和值都不能为null&#xff0c;否则会抛出NullPointerException hashtable使用方法基本上和HashMap一样 hashtable是线程安全的&#xff0c;hashmap是线程不安全 扩容机制&#xff1a; 底层有数组…...

C++入门:C语言到C++的过渡

前言&#xff1a;C——为弥补C缺陷而生的语言 C起源于 1979 年&#xff0c;当时 Bjarne Stroustrup 在贝尔实验室工作&#xff0c;面对复杂软件开发任务&#xff0c;他感到 C 语言在表达能力、可维护性和可扩展性方面存在不足。 1983 年&#xff0c;Bjarne Stroustrup 在 C 语言…...

了解MVCC

概念 MVCC&#xff0c;全称Multi-Version Concurrency Control&#xff0c;即多版本并发控制&#xff0c;是一种并发控制的方法&#xff0c;维护一个数据的多个版本&#xff0c;使得读写操作没有冲突&#xff0c;快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现…...

WPF自定义控件的应用(DynamicResource的使用方法)

1 DynamicResource的使用方法 可以在字典文件 的抬头区写入数&#xff1a; <SolidColorBrush x:Key"PrimaryBackgroundColor" Color"#FFABAdB3"/><SolidColorBrush x:Key"TextBox.MouseOver.Border" Color"#FF7EB4EA"/>&l…...

Postgresql数据库密码忘记的解决

当您忘记PostgreSQL数据库的密码时,可以通过以下步骤来重置密码。这些步骤在Windows和Linux操作系统上大体相同,但具体操作路径和命令可能有所不同。 步骤一:找到并修改pg_hba.conf文件 定位安装目录: Windows:通常在PostgreSQL的安装目录下的data文件夹中。Linux:位置可…...

Flink SQL 基础操作

Flink SQL是建立在Apache Flink之上的SQL处理引擎&#xff0c;它允许用户以SQL的方式处理流数据和批数据。以下是一些Flink SQL的基础操作&#xff1a; 一、环境准备 1.启动flink集群 ./start-cluster.sh启动sql-client ./sql-client.sh二、数据源定义 创建表&#xff08;…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

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

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

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...