【数据结构】(C语言):堆(二叉树的应用)

堆:

  • 此处堆为二叉树的应用,不是计算机中用于管理动态内存的堆。
  • 形状是完全二叉树。
  • 堆分两种:最大堆,最小堆。
  • 最大堆:每个节点比子树所有节点的数值都大,根节点为最大值。
  • 最小堆:每个节点比子树所有节点的数值都小,根节点为最小值。
  • 左右节点的数值没有顺序要求,但有左子节点才能有右子节点。
  • 一般用数组实现堆。最小堆可以实现优先队列。

注:完全二叉树:每个节点最多2个节点,倒数第二层级(含)之前层级的所有节点都有元素,最后一层级从左到右依次有元素(中间不能断)。

子树:节点及其所有子节点形成子树。(即节点,左右子节点,左右子节点的左右子节点,。。。)

根节点:没有父节点。

兄弟节点:其父节点是同一个节点。

父子节点在数组中的索引号
节点索引号(根节点为0)
节点x
父节点(x-1)// 2
左兄弟节点(右节点才有)x - 1
右兄弟节点(左节点才有)x + 1
左子节点2x + 1
右子节点2x + 2


C语言实现:(使用数组实现最小堆)

创建堆(结构体数据类型):记录数组地址和元素个数

// 堆(结构体数据类型)
typedef struct Heap
{int *p;			// 记录数组地址int n;			// 记录元素个数
} Heap;             // 别名

 (函数)堆初始化:

// 堆初始化
void init(Heap *heap, int length)
{heap->p = (int *)malloc(length * sizeof(int));    // 分配内存空间if(heap->p == NULL){perror("Memory allocation failed");exit(-1);}heap->n = 0;            // 元素个数,初始化为0
}

 创建堆变量,并初始化

Heap heap;         // 创建堆变量
init(&heap, 8);    // 设置数组最大元素个数为8

添加元素:

1、先在末尾添加元素。

2、(向上调整)与父节点比较大小,若小于父节点,与父节点交换位置,直到开头位置(根节点,数组第一个元素)。

(注:子节点索引号为x,父节点索引号为(x-1)//2)

void add(Heap *heap, int data)		// add a element to the heap
{// 往末尾添加元素heap->p[heap->n] = data;// (向上调整) 与父节点比较,小于父节点的值,与父节点交换位置int cur = heap->n;while(cur > 0){int parent = ceil((cur - 1) / 2);if(heap->p[parent] > data){heap->p[cur] = heap->p[parent];heap->p[parent] = data;cur = parent;}else break;}// 每添加一个元素,元素个数+1heap->n++;
}

删除(根节点):

1、记录根节点(数组第一个元素)和末尾节点(数组最后一个元素)。

2、末尾节点的值换到根节点位置,元素个数-1。

3、(向下调整)从根节点开始,依次与左右子节点比较大小,数值小的是父节点,直到比对到末尾。

(注:父节点索引号为x,左子节点索引号为2x+1,右子节点索引号为2x+2)

int delete(Heap *heap)			// delete root from the heap
{if(heap->n == 0) return -1;    // 空树heap->n--;                     // 每删除一次根节点,元素个数-1int root = heap->p[0], enddata = heap->p[heap->n];heap->p[0] = enddata;	       // 末尾元素换到第一个位置// (向下调整) 与左右子节点比较,若子节点小,与较小子节点交换位置int cur = 0;while(cur <= heap->n){int left = cur * 2 + 1, right = cur * 2 + 2, minchild;if(left > heap->n) break;				// 没有左子节点if(right > heap->n) minchild = left;	// 没有右子节点,有左子节点else									// 左右子节点都有的情况{// 左右子节点比较,找到较小子节点if(heap->p[right] < heap->p[left]) minchild = right;else minchild = left;// 父节点与较小子节点比较,若子节点小,与子节点交换位置if(heap->p[minchild] < enddata){heap->p[cur] = heap->p[minchild];heap->p[minchild] = enddata;cur = minchild;}else break;}}return root;
}

获取根节点:(数组第一个元素)

int getroot(Heap *heap)			// get the root from the heap
{if(heap->n == 0){printf("Empty heap\n");exit(-1);}return heap->p[0];
}

遍历堆:(类似广度遍历二叉树)

每个节点比子树的所有节点都小,但左右节点没有顺序要求。

void traverse(Heap *heap)		// show element one by one (like breadth traverse the tree)
{if(heap->n == 0) return ;printf("elements(%d): ", heap->n);for(int k = 0; k < heap->n; k++){printf("%d  ", heap->p[k]);}printf("\n");
}

清空堆:

释放数组内存空间,指向数组的指针指向NULL,元素个数为0。

void clear(Heap *heap)		// clear the heap (free memory space of the array)
{free(heap->p);          // 释放数组内存空间heap->p = NULL;         // 指针指向NULL,避免野指针heap->n = 0;            // 元素个数为0
}

 


完整代码:(heap.c)

#include <stdio.h>
#include <math.h>
#include <stdlib.h>/* structure */
typedef struct Heap
{int *p;			// memory address of the heap (array)int n;			// the number of the heap
} Heap;/* function prototype */
void init(Heap *, int);		// heap initialization
void add(Heap *, int);		// add a element to the heap
int delete(Heap *);			// delete root from the heap
int getroot(Heap *);		// get the root from the heap
void traverse(Heap *);		// show element one by one (likely breadth traverse the tree)
void clear(Heap *);			// clear the heap (free memory space of the array)/* main function */
int main(void)
{Heap heap;init(&heap, 8);printf("length: %d\n", heap.n);add(&heap, 5);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);add(&heap, 8);	add(&heap, 3);	add(&heap, 9);	add(&heap, 2);printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);delete(&heap);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);delete(&heap);	printf("root(the minimum): %d\n", getroot(&heap));traverse(&heap);clear(&heap);printf("length: %d\n", heap.n);printf("root(the minimum): %d\n", getroot(&heap));return 0;
}/* subfunction */
void init(Heap *heap, int length)		// heap initialization
{heap->p = (int *)malloc(length * sizeof(int));if(heap->p == NULL){perror("Memory allocation failed");exit(-1);}heap->n = 0;
}void add(Heap *heap, int data)		// add a element to the heap
{// add a element to the end of the heapheap->p[heap->n] = data;// (adjust up) compair with parent,if smaller than parent, change the positionint cur = heap->n;while(cur > 0){int parent = ceil((cur - 1) / 2);if(heap->p[parent] > data){heap->p[cur] = heap->p[parent];heap->p[parent] = data;cur = parent;}else break;}heap->n++;
}int delete(Heap *heap)			// delete root from the heap
{if(heap->n == 0) return -1;heap->n--;int root = heap->p[0], enddata = heap->p[heap->n];heap->p[0] = enddata;	// put the last element to the first position// (adjust down) compair with left and right child, minimun is parentint cur = 0;while(cur <= heap->n){int left = cur * 2 + 1, right = cur * 2 + 2, minchild;if(left > heap->n) break;				// no left childif(right > heap->n) minchild = left;	// have left child, no right childelse									// have left child and right child{// compair left child and right child, find smaller oneif(heap->p[right] < heap->p[left]) minchild = right;else minchild = left;// smaller child compair with parent,if child is the smallest, changeif(heap->p[minchild] < enddata){heap->p[cur] = heap->p[minchild];heap->p[minchild] = enddata;cur = minchild;}else break;}}return root;
}int getroot(Heap *heap)			// get the root from the heap
{if(heap->n == 0){printf("Empty heap\n");exit(-1);}return heap->p[0];
}void traverse(Heap *heap)		// show element one by one (like breadth traverse the tree)
{if(heap->n == 0) return ;printf("elements(%d): ", heap->n);for(int k = 0; k < heap->n; k++){printf("%d  ", heap->p[k]);}printf("\n");
}void clear(Heap *heap)		// clear the heap (free memory space of the array)
{free(heap->p);heap->p = NULL;heap->n = 0;
}

编译链接: gcc -o heap heap.c

执行可执行文件: ./heap

 

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

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

相关文章

python-opencv多态模板匹配简单代码实现

在我实验过程中发现&#xff0c;这种模板匹配如果不做任何处理只对原有图像进行匹配的话&#xff0c;好像效果很瓜 貌似是模板是1 那就只能检测出正常形态下的1&#xff0c;变大或者是 l 都不一定检测到&#xff0c; 也就是说&#xff0c;只能检测和模板图片大小尺寸颜色类别…

docker 安装 禅道

docker pull hub.zentao.net/app/zentao:20.1.1 sudo docker network create --subnet172.172.172.0/24 zentaonet 使用 8087端口号访问 使用禅道mysql 映射到3307 sudo docker run \ --name zentao2 \ -p 8087:80 \ -p 3307:3306 \ --networkzentaonet \ --ip 172.172.172.…

电脑录制视频的软件,电脑录制,4款免费软件推荐

在数字化时代&#xff0c;电脑录制视频的软件已成为我们日常生活和工作中的得力助手&#xff0c;这些软件可以帮助我们轻松捕获到屏幕上的精彩瞬间。但同时市面上的录制视频软件也层出不穷&#xff0c;让人不知该如何选择。到底怎样才能选择到一款适合自己的录屏软件呢&#xf…

【SpringBoot3学习 | 第2篇】SpringBoot3整合+SpringBoot3项目打包运行

文章目录 一. SpringBoot3 整合 SpringMVC1.1 配置静态资源位置1.2 自定义拦截器&#xff08;SpringMVC配置&#xff09; 二. SpringBoot3 整合 Druid 数据源三. SpringBoot3 整合 Mybatis3.1 Mybatis整合3.2 声明式事务整合配置3.3 AOP整合配置 四. SpringBoot3 项目打包和运行…

《Attention Is All You Need》解读

一、简介 “Attention Is All You Need” 是一篇由Ashish Vaswani等人在2017年发表的论文&#xff0c;它在自然语言处理领域引入了一种新的架构——Transformer。这个架构现在被广泛应用于各种任务&#xff0c;如机器翻译、文本摘要、问答系统等。Transformer模型的核心是“自…

小学vr虚拟课堂教学课件开发打造信息化教学典范

在信息技术的浪潮中&#xff0c;VR技术正以其独特的魅力与课堂教学深度融合&#xff0c;引领着教育方式的创新与教学方法的变革。这一变革不仅推动了“以教促学”的传统模式向“自主探索”的新型学习方式转变&#xff0c;更为学生带来了全新的学习体验。 运用信息技术融合VR教学…

深度学习1

1.支持向量机Support Vector Machine&#xff08;SVM&#xff09;是一种对数据二分类的线性分类器&#xff0c;目的是寻找一个超平面对样本进行分割&#xff0c;广泛应用人像识别&#xff0c;手写数字识别&#xff0c;生物信息识别。 二维空间分割界是一条直线&#xff0c;在三…

【基础篇】第4章 Elasticsearch 查询与过滤

在Elasticsearch的世界里&#xff0c;高效地从海量数据中检索出所需信息是其核心价值所在。本章将深入解析查询与过滤的机制&#xff0c;从基础查询到复合查询&#xff0c;再到全文搜索与分析器的定制&#xff0c;为你揭开数据检索的神秘面纱。 4.1 基本查询 4.1.1 Match查询…

Qt——升级系列(Level Seven):事件、文件

目录 Qt事件 事件介绍 事件的处理 按键事件 鼠标事件 定时器 事件分发器 事件过滤器 Qt文件 Qt文件概述 输入输出设备类 文件读写类 文件和目录信息类 Qt事件 事件介绍 事件是应⽤程序内部或者外部产⽣的事情或者动作的统称。在 Qt 中使⽤⼀个对象来表⽰⼀个事件。所有的 Qt …

工商业光伏项目如何快速开发?

一、前期调研与规划 1、屋顶资源评估&#xff1a;详细测量屋顶面积、承重能力及朝向&#xff0c;利用光伏业务管理软件进行日照分析和发电量预测&#xff0c;确保项目可行性。 2、政策与补贴研究&#xff1a;深入了解当地政府对工商业光伏项目的政策支持和补贴情况&#xff0…

JVM原理(十四):JVM虚拟机运行时栈帧结构

Java虚拟机已方法作为最基本的执行单位。 栈帧&#xff1a;是支持Java虚拟机进行方法调用和方法执行背后的数据结构。 栈帧存储了方法的 局部变量表、操作数栈、动态连接和放回地址等信息。 每一个方法的调用开始和执行结束&#xff0c;都对应着一个栈帧在虚拟机栈里面从入栈…

Linux文件与日志

目录 1. Linux 文件系统 1.1 inode号 1.2 EXT类型文件恢复 1.3 xfs类型文件备份和恢复 2. 日志分析 2.1 日志类型 2.2日志配置文件 2.3 日志分析的重要性 在Linux系统中&#xff0c;文件和日志是管理和维护系统运行所不可或缺的。理解它们的工作原理和如何有效地管理和…

驱动开发:配置Visual Studio驱动开发环境

100编程书屋_孔夫子旧书网 配置驱动开发环境配置驱动开发模板配置驱动双机调试 在正式开始驱动开发之前&#xff0c;需要自行搭建驱动开发的必要环境&#xff0c;首先我们需要安装Visual Studio 2013这款功能强大的程序开发工具&#xff0c;在课件内请双击ISO文件并运行内部的…

2009-2024年第一季度上市公司华证ESG评级季度数据

2009-2024年第一季度上市公司华证ESG评级季度数据 1、时间&#xff1a;2009-2024年第一季度 2、指标&#xff1a;证券代码、证券简称、评级日期、综合评级、综合得分、E评级、E得分、S评级、S得分、G评级、G得分、证监会行业&#xff08;新&#xff09;、同花顺行业&#xff…

Visio框图自动带填充色原因及如何取消

0 Preface/Foreword Visio&#xff0c;Windows的一个流程图&框图制作工具。 1 新建Visio文件 1.1 图形带填充 新建Visio时候&#xff0c;如果选择了模版&#xff0c;那么就后期使用的工具元素会自动填充。 带来的弊端&#xff0c;在元素编辑文字时&#xff0c;如果此时不…

苹果公司的Wifi定位服务(WPS)存在被滥用的风险

安全博客 Krebs on Security 2024年5月21日发布博文&#xff0c;表示苹果公司的定位服务存在被滥用风险&#xff0c;通过 "窃取"WPS 数据库&#xff0c;可以定位部队行踪。 相关背景知识 手机定位固然主要依赖卫星定位&#xff0c;不过在城市地区&#xff0c;密集的…

新建Vue工程的几种方法

文章目录 使用CLI2 : vue-cli使用CLI3 : vue/cli使用 vue3构建 &#xff08;内置Vite&#xff09;直接使用Vite使用parcel (最少配置方案) 使用CLI2 : vue-cli vue-cli是针对构建vue的脚手架CLI2&#xff0c;只能新建vue2工程。 全局安装vue-cli之后&#xff0c;构建vue2项目的…

03.C1W2.Sentiment Analysis with Naïve Bayes

目录 Probability and Bayes’ RuleIntroductionProbabilitiesProbability of the intersection Bayes’ RuleConditional ProbabilitiesBayes’ RuleQuiz: Bayes’ Rule Applied Nave Bayes IntroductionNave Bayes for Sentiment Analysis P ( w i ∣ c l a s s ) P(w_i|clas…

npm 淘宝镜像证书过期,错误信息 Could not retrieve https://npm.taobao.org/mirrors/node/latest

更换 npm 证书 问题描述报错原因更换步骤1 找到 nvm 安装目录2 发现证书过期3 更换新地址4 保存后&#xff0c;重新安装成功 问题描述 在使用 nvm 安装新版本时&#xff0c;未成功&#xff0c;出现报错&#xff1a; Could not retrieve https://npm.taobao.org/mirrors/node/l…

【postgresql】表操作

创建表 (CREATE TABLE): CREATE TABLE table_name ( column1 data_type constraint,column2 data_type constraint,... ); 插入数据 (INSERT INTO): INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...); 查询数据 (SELECT): SELECT column1, c…