101.【C语言】数据结构之二叉树的堆实现(顺序结构) 2

目录

1.堆删除函数HeapPop

一个常见的错误想法:挪动删除

正确方法

设计堆顶删除函数HeapPop

解析向下调整函数AdjustDown

核心思想

向下调整最多次数

向下调整的前提

代码实现

提问

细节分析

2.测试堆删除函数

运行结果

3.引申问题

运行结果

4.练习

分析

代码

执行过程图

运行结果


承接100.【C语言】数据结构之二叉树的堆实现 上文章

1.堆删除函数HeapPop

尾删没有任何意义,删头才有意义(即删堆顶),删除之后要调整二叉树,仍然符合大根堆的性质

4a8a9f7d39254681a769468057a7906f.png

拿上图举例,现删除堆顶元素50

一个常见的错误想法:挪动删除

即{50,30,8,5,12,0,2,15,3}变成{30,8,5,12,0,2,15,3}

将{30,8,5,12,0,2,15,3}画成二叉树会发现既不是大根堆也不是小根堆

此错误方法不仅效率低下还将父子兄弟之间的关系全部弄乱了

因此禁止使用挪动删除!

正确方法

让堆顶元素和数组的最后一个元素进行交换(Swap函数),接着删除最后一个元素(ps->size--),再向下调整

设计堆顶删除函数HeapPop

堆顶能删除的前提:堆不能是空的(调用HeapEmpty函数检验)

空堆检查函数HeapEmpty

bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}

交换函数Swap

void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a,php->size,0);
}

解析向下调整函数AdjustDown

核心思想

左孩子和右孩子哪一个大,parent就换哪个,重复前述步骤直到满足大根堆或小根堆的性质

以下面这个为例说明

835ce423296641c2add5b98f83402f3f.png

384ad47ca9314a0da1892db952184bc3.png 经过两次向下调整后,变成大根堆6ea34274685747ad87b4d8f45aceac2a.png

向下调整最多次数

最坏情况是调整到叶节点,即eq?log_2%20N

向下调整的前提

左右子树为堆

代码实现

一开始默认为左孩子,如果右孩子值大于左孩子,则进行调整

void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (a[child + 1] > a[child]){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = child * 2 + 1;}else{break;}}
}
提问

上述代码写的有没有问题?

答:if (a[child + 1] > a[child])有潜在的问题,可能会越界访问

child+1可能会大于或等于n

细节分析

改成下面这样行吗?

if (a[child + 1] > a[child] && child+1 < n)

不行,要遵循&&的运算规则:先左后右,因此上方代码会先判断a[child + 1] > a[child]再判断child+1 < n,可能会先越界访问,之后判断child+1 < n就无效了

因此改为

if (child+1 < n && a[child + 1] > a[child])

2.测试堆删除函数

main.c中写入以下代码,之后下断点至return 0;

#include "Heap.h"
int main()
{HP hp;HeapInit(&hp);HeapPush(&hp, 1);HeapPush(&hp, 3);HeapPush(&hp, 0);HeapPush(&hp, 5);HeapPush(&hp, 8);HeapPush(&hp, 12);HeapPush(&hp, 2);HeapPush(&hp, 5);HeapPush(&hp, 30);HeapPush(&hp, 50);while (!HeapEmpty(&hp)){printf("%d ", HeapTop(&hp));HeapPop(&hp);}return 0;}

备注:只要堆没有删空while (!HeapEmpty(&hp))就继续执行,这里要强调的点是:堆顶永远是堆中最大的数,因此只有删了堆顶,堆顶下面最大的数才能上去

运行结果

625d4ea62d074a95b574443449bc8c8d.png

显然进行了堆排序

3.引申问题

若要打印上方排好序的堆中的前k个数(k<=n),代码怎么写?

答:稍加改动即可

	int k = 0;scanf("%d", &k);while (!HeapEmpty(&hp)&&k--){printf("%d ", HeapTop(&hp));HeapPop(&hp);}

运行结果

f04e34b7e2254d3ebd1b8b4a901eb4ac.png

4.练习

给一个乱序数组,设计一个排序函数HeapSort,要求建立大根堆,写出代码

要求:不另外开辟空间

代码模板

??? HeapSort(??????)
{//??????
}int main()
{int arr[] = { 1,4,2,5,7,2,6,8,9,2 };HeapSort(??????);return 0;
}

分析

在无序堆(既不是大根堆也不是小根堆)上建立大根堆,则需要对数组中的每一个元素进行向上调整

,则可写循环

代码

向上调整建堆

void HeapSort(int* arr, int n)
{for (int i = 1; i < n; i++){AdjustUp(arr, i);}
}
int main()
{int arr[] = { 1,4,2,5,7,2,6,8,9,2 };int size = sizeof(arr)/sizeof(arr[0]);HeapSort(arr,size);return 0;
}

执行过程图

a8428c7bd9ec44b2a486749ff9fdb53c.png

运行结果

e2b869a4b14549dc898e8fad0909b97a.png

5.堆的销毁函数HeapDestory

先释放内存,再设置结构体成员变量

void HeapDestory(HP* php)
{assert(php);free(php->a);php->a = NULL;php->capacity = php->size = 0;
}

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

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

相关文章

【机器学习chp8】统计学习理论

前言 本文遗留问题&#xff1a;无 目录 前言 一、结构风险最小化 1、最小化风险决策 2、分类与回归中的最小化风险决策 3、统计学习的基本目标 4、无免费午餐定理 5、Hoeffding不等式 &#xff08;1&#xff09;背景及定义 &#xff08;2&#xff09;Hoeffding不等式…

Springboot启动报错’javax.management.MBeanServer’ that could not be found.

报错信息如下图&#xff1a; 解决办法&#xff1a; 1.在你的.yml文件或者.properties文件里加上如下配置&#xff1a; properties: management.endpoints.jmx.enabledfalseyml: management:endpoints:jmx:enabled: false2.如果以上方法行不通&#xff0c;在springboot启动类…

英语知识网站:Spring Boot技术构建

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

英伟达推出了全新的小型语言模型家族——Hymba 1.5B

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

spring boot2.7集成OpenFeign 3.1.7

1.Feign Feign是一个声明式web服务客户端。它使编写web服务客户端更容易。要使用Feign&#xff0c;请创建一个接口并对其进行注释。它具有可插入注释支持&#xff0c;包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持&…

Jmeter中的前置处理器

5&#xff09;前置处理器 1--JSR223 PreProcessor 功能特点 自定义数据处理&#xff1a;使用脚本语言处理请求数据&#xff0c;实现高度定制化的数据处理和生成。动态数据生成&#xff1a;在请求发送前生成动态数据&#xff0c;如随机数、时间戳等。变量设置&#xff1a;设置…

git(Linux)

1.git 三板斧 基本准备工作&#xff1a; 把远端仓库拉拉取到本地了 .git --> 本地仓库 git在提交的时候&#xff0c;只会提交变化的部分 就可以在当前目录下新增代码了 test.c 并没有被仓库管理起来 怎么添加&#xff1f; 1.1 git add test.c 也不算完全添加到仓库里面&…

学习Java的日子 Day56 数据库连接池,Druid连接池

Day56 1.数据库连接池 理解&#xff1a;池就是容器&#xff0c;容器中存放了多个连接对象 使用原因&#xff1a; 1.优化创建和销毁连接的时间&#xff08;在项目启动时创建连接池&#xff0c;项目销毁时关闭连接池&#xff09; 2.提高连接对象的复用率 3.有效控制项目中连接的…

Jmeter测试工具的安装和使用,mac版本,jmeter版本5.2.1

Jmeter测试工具的安装和使用JSON格式请求 一、安装1、安装jdk包和设置java环境2、去官网下载Jmeter3、解压后&#xff0c;打开mac终端&#xff0c;进入apache-jmeter的bin文件开启jmeter 二、使用jmeter1、添加线程2、添加HTTP请求3、配置请求的协议、IP地址、端口号、请求方法…

Envoy 源码解析(一):Envoy 整体架构、Envoy 的初始化

本文基于 Envoy 1.31.0 版本进行源码学习 1、Envoy 整体架构 1&#xff09;、核心组件 Envoy 包含以下四个核心组件&#xff1a; Listener&#xff08;监听器&#xff09;&#xff1a;定义了 Envoy 如何处理入站请求。一旦连接建立&#xff0c;请求会被传递给一组过滤器进行处…

【VUE3】VUE组合式(响应式)API常见语法

pnpm常用命令 pnpm i //pnpm安装VUE3常见语法汇总 ref() //const count ref(0) //count.value&#xff08;访问值&#xff0c;包括对象要加.value&#xff09; //任何类型的值&#xff0c;包括深层嵌套的对象或则JS内置数据结构 await nextTick() //要等待 DOM 更新完成后…

CGAL CGAL::Polygon_mesh_processing::self_intersections解析

CGAL::Polygon_mesh_processing::self_intersections 是用于检测多边形网格&#xff08;Polygon Mesh&#xff09;中的自相交的函数。自相交是指网格中的某些面&#xff08;例如三角形&#xff09;与同一网格中的其他面交叉的情况。这种情况通常是不期望的&#xff0c;因为它会…

⭐ Unity 资源管理解决方案:Addressable_ Demo演示

一、使用Addressable插件的好处&#xff1a; 1.自动管理依赖关系 2.方便资源卸载 3.自带整合好的资源管理界面 4.支持远程资源加载和热更新 二、使用步骤 安装组件 1.创建资源分组 2.将资源加入资源组 3.打包资源 4.加载资源 三种方式可以加载 using System.Collections…

Vue前端开发2.3.5 条件渲染指令

本文介绍了Vue中两种条件渲染指令&#xff1a;v-if和v-show。v-if通过布尔值控制元素的DOM树存在&#xff0c;适用于不频繁切换显示状态的场景&#xff1b;v-show则通过CSS的display属性控制显示&#xff0c;适合频繁切换。通过创建单文件组件示例&#xff0c;演示了如何使用这…

GitLab指定用户分配合并权限

进入项目 -》 Project Settings Repository -》展开 Protected branches -》 添加要保护的分支&#xff0c;设置角色 管理用户角色权限 查看到不同用户的角色&#xff0c;一般设置Developer只有Merger Request权限&#xff0c;Maintainer还有Merge审批权限 GitLab 中的权限…

计算机网络socket编程(5)_TCP网络编程实现echo_server

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络socket编程(5)_TCP网络编程实现echo_server 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交…

C++ 二叉搜索树(Binary Search Tree, BST)深度解析与全面指南:从基础概念到高级应用、算法优化及实战案例

&#x1f31f;个人主页&#xff1a;落叶 &#x1f31f;当前专栏: C专栏 目录 ⼆叉搜索树的概念 ⼆叉搜索树的性能分析 ⼆叉搜索树的插⼊ ⼆叉搜索树的查找 二叉搜索树中序遍历 ⼆叉搜索树的删除 cur的左节点为空的情况 cur的右节点为空的情况 左&#xff0c;右节点都不为…

uniCloud云开发

uniCloud 是 DCloud 联合阿里云、腾讯云、支付宝云&#xff0c;为开发者提供的基于 serverless 模式和 js 编程的云开发平台。 普通云函数 callFuction方式云函数&#xff0c;也称之为普通云函数 uni-app的前端代码&#xff0c;不再执行uni.request联网&#xff0c;而是通过…

org.apache.log4j的日志记录级别和基础使用Demo

org.apache.log4j的日志记录级别和基础使用Demo&#xff0c;本次案例展示&#xff0c;使用是的maven项目&#xff0c;搭建的一个简单的爬虫案例。里面采用了大家熟悉的日志记录插件&#xff0c;log4j。来自apache公司的开源插件。 package com.qian.test;import org.apache.log…

day05(单片机高级)PCB基础

目录 PCB基础 什么是PCB&#xff1f;PCB的作用&#xff1f; PCB的制作过程 PCB板的层数 PCB设计软件 安装立创EDA PCB基础 什么是PCB&#xff1f;PCB的作用&#xff1f; PCB&#xff08;Printed Circuit Board&#xff09;&#xff0c;中文名称为印制电路板&#xff0c;又称印刷…