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

暴力数据结构之二叉树(堆的相关知识)

1. 堆的基本了解

        堆(heap)是计算机科学中一种特殊的数据结构,通常被视为一个完全二叉树,并且可以用数组来存储。堆的主要应用是在一组变化频繁(增删查改的频率较高)的数据集中查找最值。堆分为大根堆和小根堆,大根堆中任意节点的值都大于其子树中节点的值,而小根堆则相反。堆的存储方式遵循层序遍历的规则,这样可以高效地利用存储空间。在数组中,根节点的下标为0,节点的左右孩子的下标可以通过特定的公式计算得出。堆的实现通常利用动态数组,这样可以快速扩展容量而不造成空间浪费。

堆的一些性质:1.堆中某个结点的值总是不大于或不小于其父结点的值;

                         2.堆总是一棵完全二叉树。

2. 堆的实现

 我们知道堆的逻辑结构是一个完全二叉树,但是其物理结构仍然是一个数组,所以实现堆创建一个数组即可。

typedef int HPDateType;typedef struct Heap
{HPDateType* a;int size;int capacity;
}HP;void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size = 0;
}
void HPDesTroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->capacity = php->size = 0;
}void Swap(HPDateType* p1, HPDateType* p2)
{HPDateType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDateType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDateType x)
{if (php->capacity == php->size){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* tmp = (HPDateType*)realloc(php->a, sizeof(HPDateType) * newcapacity);if (tmp = NULL){perror("realloc");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
void AdjustDown(HPDateType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}HPDateType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
2.1 堆的插入

大堆的父节点均大于子节点,小堆恰好相反,自然实现逻辑各不相同,这里主要有两个主要的思想就是"父子值交换","父子址交换"。解释就是(以小堆为例):

如果对一个已有的小堆插入新的数据(叶子),如果这个叶子与他的父节点相比更小,就与父节点交换,再与交换后节点所属的父节点对比,如果还是小于就继续交换。

 代码解释如下: 

当要插入数据时先将其放在叶子节点(数组尾部),通过AdjustUp函数可以实现向上比较的动作,当然插入前判断空间是否充足,适当扩容即可。

void AdjustUp(HPDateType* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HPPush(HP* php, HPDateType x)
{if (php->capacity == php->size){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* tmp = (HPDateType*)realloc(php->a, sizeof(HPDateType) * newcapacity);if (tmp = NULL){perror("realloc");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;AdjustUp(php->a, php->size - 1);
}
2.2 堆的删除

堆的删除就是将根节点与叶子节点交换后直接删除交换后的叶子节点(即最初的跟节点数据),然后将交换后的根节点逐渐向下交换,如图所示:

 通过代码展示就是,先交换根节点与叶子结点(即数组头尾交换)然后直接删除交换后的叶子结点。创建一个AdjustDown函数,逐层下沉交换后的跟节点,保持仍然是一个堆。

void AdjustDown(HPDateType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] > a[child + 1]){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HPPop(HP* php)
{assert(php);assert(php->size > 0);Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);
}

3.堆排序

主要思路:升序建大堆,降序建小堆

解释:以升序为例,创建一个大堆,即根节点为最大的数据,此时要排序,就直接将根节点与叶子结点交换(数组首尾交换),然后数组末尾的下标向前移动(此时数组末尾的数据不会参与后续运算),然后将交换后的跟节点使用AdjustDown函数下沉,以此类推,最后原数组就是一个升序排列。同理小堆也是如此。

为什么升序不用小堆呢,因为小堆每一次运算都要再次创建一个数组,浪费更多的内存,可以使用但是不推荐。同理这也是为什么降序使用小堆。

具体代码如下

void HeapSort(int* a, int n)
{// 降序,建小堆// 升序,建大堆for (int i = 1; i < n; i++){AdjustUp(a, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

相关文章:

暴力数据结构之二叉树(堆的相关知识)

1. 堆的基本了解 堆&#xff08;heap&#xff09;是计算机科学中一种特殊的数据结构&#xff0c;通常被视为一个完全二叉树&#xff0c;并且可以用数组来存储。堆的主要应用是在一组变化频繁&#xff08;增删查改的频率较高&#xff09;的数据集中查找最值。堆分为大根堆和小根…...

死锁调试技巧:工作线程和用户界面线程

有人碰到了一个死锁问题&#xff0c;找到我们想请我们看看&#xff0c;这个是关于应用程序用户界面相关的死锁问题。 我也不清楚他为什么会找上我们&#xff0c;可能是因为我们经常会和窗口管理器打交道吧。 下面&#xff0c;我们来看看死锁的两个线程。 >> 请移步至 …...

蓝桥杯-外卖店优先级(简单写法)

“饱了么”外卖系统中维护着 N 家外卖店&#xff0c;编号 1∼N。 每家外卖店都有一个优先级&#xff0c;初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位&#xff0c;如果外卖店没有订单&#xff0c;则优先级会减少 1&#xff0c;最低减到 0&#xff1b;而如果外卖店有订…...

VueRouter使用总结

VueRouter 是 Vue.js 的官方路由管理器&#xff0c;用于构建单页面应用&#xff08;SPA&#xff09;。在使用 VueRouter 时&#xff0c;开发者可以定义路由映射规则&#xff0c;并在 Vue 组件中通过编程式导航或声明式导航的方式控制页面的跳转和展示。以下是 VueRouter 使用的…...

Flink checkpoint 源码分析- Checkpoint snapshot 处理流程

背景 在上一篇博客中我们分析了代码中barrier的是如何流动传递的。Flink checkpoint 源码分析- Checkpoint barrier 传递源码分析-CSDN博客 最后跟踪到了代码org.apache.flink.streaming.runtime.io.checkpointing.CheckpointedInputGate#handleEvent 现在我们接着跟踪相应…...

Leaflet.canvaslabel在Ajax异步请求时bindPopup无效的解决办法

目录 前言 一、场景重现 1、遇到问题的代码 2、问题排查 二、通过实验验证猜想 1、排查LayerGroup和FeatureGroup 2、排查Leaflet.canvaslabel.js 三、柳暗花明又一村 1、点聚类的办法 2、歪打正着 总结 前言 在上一篇博客中介绍了基于SpringBoot的全国风景区WebGIS按…...

Go 处理错误

如果你习惯了 try catch 这样的语法后&#xff0c;会觉得处理错误真简单&#xff0c;然后你再来接触 Go 的错误异常&#xff0c;你会发现他好复杂啊&#xff0c;怎么到处都是 error&#xff0c;到处都需要处理 error。 首先咱们需要知道 Go 语言里面有个约定&#xff0c;就是一…...

python读取excel数据写入mysql

概述 业务中有时会需要解析excel中的数据&#xff0c;按照要求处理后&#xff0c;写入到db中&#xff1b; 用python处理这个正好简便快捷 demo 没有依赖就 pip install pymysql一下 import pymysql from pymysql.converters import escape_string from openpyxl import loa…...

flutter日期选择器仅选择年、月

引入包&#xff1a;flutter_datetime_picker: 1.5.0 封装 import package:flutter/cupertino.dart; import package:flutter/material.dart; import package:flutter_datetime_picker/flutter_datetime_picker.dart;class ATuiDateTimePicker {static Future<DateTime> …...

素数筛详解c++

一、埃式筛法 代码 二、线性筛法&#xff08;欧拉筛法&#xff09; 主要的思想就是一个质数的倍数(倍数为1除外)肯定是合数&#xff0c;那么我们利用这个质数算出合数&#xff0c;然后划掉这个合数&#xff0c;下次就可以不用判断它是不是质数&#xff0c;节省了大量的时间。 …...

【Python超详细的学习笔记】Python超详细的学习笔记,涉及多个领域,是个很不错的笔记

获取笔记链接 Python超详细的学习笔记 一&#xff0c;逆向加密模块 1&#xff0c;Python中运行JS代码 1.1 解决中文乱码或者报错问题 import subprocess from functools import partial subprocess.Popen partial(subprocess.Popen, encodingutf-8) import execjs1.2 常用…...

TINA 使用教程

常用功能 分析-电气规则检查&#xff1a;短路&#xff0c;断路等分析- 直流分析 交流分析 瞬态分析 视图-分离曲线 由于输出的容性负载导致的振荡 增加5欧电阻后OK 横扫参数 添加横扫曲线的电阻&#xff0c;选择R3&#xff1a;8K-20K PWL和WAV文件的支持 示例一&#xff1a;…...

weblogic 任意文件上传 CVE-2018-2894

一、漏洞简介 在 Weblogic Web Service Test Page 中存在一处任意文件上传漏洞&#xff0c; Web Service Test Page 在"生产模式"下默认不开启&#xff0c;所以该漏洞有一定限制。利用该 漏洞&#xff0c;可以上传任意 jsp 文件&#xff0c;进而获取服务器权限。 二…...

我的第一个网页:武理天协

1. html代码 1.1 首页.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>武理天协</title><link rel"stylesheet" href"./style.css"><link rel"stylesh…...

机器学习笔记 KAN网络架构简述(Kolmogorov-Arnold Networks)

一、简述 在最近的研究中,出现了号称传统多层感知器 (MLP) 的突破性替代方案,重塑了人工神经网络 (ANN) 的格局。这种创新架构被称为柯尔莫哥洛夫-阿诺德网络 (KAN),它提出了一种受柯尔莫哥洛夫-阿诺德表示定理启发的函数逼近的方法。 与 MLP 不同,MLP 依赖于各个节…...

基于网络爬虫技术的网络新闻分析(二)

目录 2 系统需求分析 2.1 系统需求概述 2.2 系统需求分析 2.2.1 系统功能要求 2.2.2 系统IPO图 2.2 系统非功能性需求分析 3 系统概要设计 3.1 设计约束 3.1.1 需求约束 3.1.2 设计策略 3.1.3 技术实现 3.3 模块结构 3.3.1 模块结构图 3.3.2 系统层次图 3.3.3…...

Java--初识类和对象

前言 本篇讲解Java类和对象的入门版本。 学习目的&#xff1a; 1.理解什么是类和对象。 2.引入面向对象程序设计的概念 3.学会如何定义类和创建对象。 4.理解this引用。 5.了解构造方法的概念并学会使用 考虑到篇幅过长问题&#xff0c;作者决定分多次发布。 面向对象的引入 J…...

SpringBoot如何实现动态数据源?

在Spring Boot中实现动态数据源主要涉及到创建和管理不同的数据源&#xff0c;并在运行时根据需要切换。这可以通过编程方式配置Spring的AbstractRoutingDataSource来完成。下面我会逐步介绍如何实现动态数据源&#xff0c;并给出代码示例。 第1步&#xff1a;添加依赖 首先&…...

win10安装mysql8.0+汉化

一、官网安装 MySQL 1. 在mysql官网进行下载页面 2. 下滑页面&#xff0c;选择 MySQL community download 3.下载windows版本 4.选择第二个download 5.不用登陆&#xff0c;no thanks&#xff0c;just start my download. 6.下载 二、安装 1. 双击安装 2. 选 Full->next 3…...

全网最全的Postman接口自动化测试!

该篇文章针对已经掌握 Postman 基本用法的读者&#xff0c;即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求的操作。 当前环境&#xff1a; Window 7 - 64 Postman 版本&#xff08;免费版&#xff09;&#xff1a;Chrome App v5.5.3 不同版本页面 UI 和部分…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...