数据结构:二叉树、堆

目录

一.树的概念

二、二叉树

1.二叉树的概念

2.特殊类型的二叉树

3.二叉树的性质

4.二叉树存储的结构

三、堆

1.堆的概念

2.堆的实现

Heap.h

Heap.c


一.树的概念

 注意,树的同一层中不能有关联,否侧就不是树了,就变成图了,例如:

由于B和C存在关联,这就不是树了。 

有关树的一些重要概念:

二、二叉树

1.二叉树的概念

二叉树由一个根节点加上两棵别称为左子树和右子树的二叉树组成

它具有两个特点:不存在度大于2的节点;子树有左右之分,次序不能颠倒,故二叉树是有序树

各类型二叉树集合:

2.特殊类型的二叉树

满二叉树:所有非叶子节点都有两个子节点,且所有叶子节点都在同一层

完全二叉树:除了最后一层,每一层都是满的,且最后一层的叶子节点都尽可能靠左排列 

二叉排序树:左子树所有节点的值小于根节点的值,右子树所有节点的值大于根节点的值,且左右子树也分别是二叉排序树

3.二叉树的性质

(1) 对于具有n个节点的完全二叉树,如果按照从上到下从左到右的顺序对所有节点从0开始编号,则序号为i的节点有:其双亲节点序号为(i-1)/2;其左孩子节点序号为i*2+1,右孩子节点序号为i*2+2,注意i*2+1和i*2+2要小于n,合法性

(2)规定根节点层数为1,具有n个节点的满二叉树深度为h=log2(n+1)

(3)规定根节点层数为1,第i层最大节点数为2^(i-1)

(4)规定根节点层数为1,深度为h的二叉树的最大节点数为2^h-1

4.二叉树存储的结构

分为顺序存储结构和链式存储结构,其中用顺序存储结构来实现完全二叉树就是接下来重点介绍的堆。

链式存储:用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。

顺序存储:顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

、堆

1.堆的概念

堆可以看作一种特殊类型的完全二叉树,分为大堆和小堆,根节点最大的称为大堆,根节点最小的称为小堆。

大堆:谁大谁当爹,但兄弟间无绝对大小关系

小堆:谁小谁当爹,但兄第间无绝对大小关系

2.堆的实现

升序:建大堆

降序:建小堆

接下来给出建小堆的代码实现:

Heap.h

#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<stdbool.h>typedef int HDataType;
typedef struct Heap
{HDataType* arr;int size;int capacity;
}Heap;//堆的初始化
void HeapInit(Heap* obj);
// 堆的插入
void HeapPush(Heap* obj, HDataType x);
// 堆的删除
void HeapPop(Heap* obj);
// 取堆顶的数据
HDataType HeapTop(Heap* obj);
// 堆的数据个数
int HeapSize(Heap* obj);
// 堆的判空
bool HeapEmpty(Heap* obj);
// 堆的销毁
void HeapDestroy(Heap* obj);

Heap.c

#include"Heap.h"void HeapInit(Heap* php)
{php->capacity = php->size = 0;php->arr = NULL;
}//扩容
void Exp(Heap* obj)
{if (obj->size == obj->capacity){int new_capeccity = obj->capacity == 0 ? 4 : obj->capacity * 2;HDataType* tem = (HDataType*)realloc(obj->arr, sizeof(HDataType) * new_capeccity);if (tem == NULL){assert("realloc");}obj->arr = tem;obj->capacity = new_capeccity;}
}//交换
void Swap(HDataType* child, HDataType* parent)
{HDataType tem = *child;*child = *parent;*parent = tem;
}//向上调整
//这里假设是小堆进行调整
//如果是大堆,将if处改为大于号即可
void UpAdjust(HDataType* p,int child)
{//通过计算找父母HDataType parent = (child - 1) / 2;while (child > 0){if (p[child] < p[parent]){//交换Swap(&p[child], &p[parent]);//交换后,将parent的位置给给child,继续计算下一个parentchild = parent;//把父母给孩子parent = (child - 1) / 2;//得到新的父母}else{break;}}
}//插入
//先向堆尾插入元素,再根据大堆还是小堆向上调整
void HeapPush(Heap* obj,HDataType x)
{assert(obj);Exp(obj);obj->arr[obj->size] = x;obj->size++;//这个时候我们需要向上UpAdjust(obj->arr, obj->size - 1);
}//向下调整
//这里假设是小堆
//如果是大堆,将两个if处改为大于号即可
void DownAdjust(HDataType* p,int n,int parent)
{//计算出左孩子int child = parent * 2 + 1;while (child < n){if (child + 1 < n && p[child + 1] < p[child]) {//如果右儿子小于左儿子,直接++到右儿子的位置++child;//child+1<n是为了避免越界访问,因为每次算出的是左孩子,堆尾不一定是右孩子}if (p[child] < p[parent])//如果child<parent,就交换,要把小的往上走{//这边操作一样,算法不同Swap(&p[child], &p[parent]);parent = child;//把孩子给父母child = parent * 2 + 1;//得到新的孩子}else{break;}}
}//删除堆顶元素
//这里是小堆,删的实际是最小元素
void HeapPop(Heap* obj)
{assert(obj);assert(obj->arr);assert(obj->size > 0);//堆内无元素则不存在删的问题//1.先交换堆顶和堆尾的元素,避免中间节点之间关系全部混乱Swap(&obj->arr[0], &obj->arr[obj->size - 1]);//2.删obj->size--;//3.这里我们假设的是小堆,而当前交换后显然不是小堆,故向下调整,将堆中次小元素调到堆顶DownAdjust(obj->arr, obj->size, 0);
}//获取堆顶元素
HDataType HeapTop(Heap* obj)
{assert(obj);return obj->arr[0];
}//获取堆中数据的个数
int HeapSize(Heap* obj)
{assert(obj);return obj->size;
}//判空
bool HeapEmpty(Heap* obj)
{assert(obj);return obj->size == 0;
}//堆的销毁
void HeapDestroy(Heap* obj)
{assert(obj);assert(obj->arr);free(obj->arr);obj->arr = NULL;obj->capacity = obj->size = 0;
}

test.c

 cl:以上代码和顺序表的实现是很相似的,最大区别是堆独有的特点,也就是建堆,堆尾插入元素时进行向上调整,堆顶删除元素时进行向下调整,这两步是最关键的算法,是保证堆的特点(大小堆)的关键。

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

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

相关文章

RequestBody接收参数报错com.fasterxml.jackson.databind.exc.MismatchedInputException

目录&#xff1a; 1、错误现象2、解决办法3、最终验证 1、错误现象 报错的现象和代码如下&#xff1a; 2、解决办法 查了很多都说参数类型对不上&#xff0c;但是明明是对上的&#xff0c;没有问题&#xff0c;最后只有换接收方式后验证是可以的&#xff1b;最终想了一下&…

效果不错的论文介绍:Im2Flow2Act:-跨领域机器人操控技术

Im2Flow2Act: 跨领域机器人操控技术 简介 今天介绍一个比较惊艳的论文&#xff0c;Im2Flow2Act&#xff0c;可以预测应该怎么移动图象中的物体预测移动方法完成需要执行的动作任务。 Im2Flow2Act 是一个基于学习的机器人操控框架&#xff0c;旨在通过多种数据源为机器人提供操…

计算DOTA文件的IOU

背景 在目标检测任务中&#xff0c;评估不同对象之间的重叠情况是至关重要的&#xff0c;而IOU&#xff08;Intersection Over Union&#xff09;是衡量这种重叠程度的重要指标。本文将介绍如何编写一个Python脚本&#xff0c;通过并行化处理DOTA格式的标注文件&#xff0c;统…

vue3 解决背景图与窗口留有间隙的问题

需要实现一个登录界面&#xff0c;login.vue的代码如下&#xff1a; <script> import { ref } from vue;export default {setup() {return {};}, }; </script><template><div id"login-container" class"login-container"><di…

线程的同步

文章目录 线程的同步同步&#xff1a;条件变量&#xff1a;pthread_cond_init():pthread_cond_wait()pthread_cond_signalpthread_cond_broadcast cp问题伪唤醒 信号量**多线程的互斥用信号量**&#xff1a;**单线程的互斥用锁**&#xff1a; 线程的同步 同步&#xff1a; 让…

Cesium 影像加载的TileReplacementQueue技术

本文以分析QuadtreePrimitive及相关影像内容&#xff0c;讨论一些流程和方法。影像和地形是Cesium的基础内容&#xff0c;但是有时候感觉这部分的加载和渲染效率并不高。 TileReplacementQueue是一个非常神奇的类&#xff0c;我自己研究了小半天。虽然结构简单&#xff0c;但是…

ACH支付详解,北美电商为何偏爱这一方式

ACH支付在北美广泛应用&#xff0c;低成本、可逆、安全、便捷。ZohoBooks财务管理软件支持ACH&#xff0c;可自动化处理收付款&#xff0c;提高效率并减少错误。适合北美电商客户使用&#xff0c;支持多货币和税务法规。 一、什么是ACH支付&#xff1f; ACH支付是一种通过名为…

②PROFINET转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899 协议转换通信网关 PROFINET 转 Modbus TCP &#xff08;接上一章&#xff09; 配置使用 与 PROFINET 主站进行组态说明 这里介绍与西门子 PLC 的…

大数据-180 Elasticsearch - 原理剖析 索引写入与近实时搜索

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Docker-Consul概述以及集群环境搭建

文章目录 一、Docker consul概述二、consul 部署1.consul服务器2.registrator服务器&#xff08;客户端&#xff09;2.consul-template&#xff08;在consul服务器&#xff09;3.consul 多节点 一、Docker consul概述 容器服务更新与发现&#xff1a;先发现再更新&#xff0c;…

leetcode289:生命游戏

根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态&#xff1a; 1 即为 活细胞 &am…

ClickFix攻击活动升级:可通过虚假谷歌会议画面传播恶意软件

最近&#xff0c;研究人员报告了一种新的 ClickFix 攻击活动&#xff0c;主要通过诱骗用户访问显示虚假连接错误的欺诈性 谷歌会议的页面&#xff0c;继而借此传播信息窃取恶意软件&#xff0c;主要针对 Windows 和 macOS 操作系统。 ClickFix是网络安全公司Proofpoint在5月份…

016集——c# 实现CAD类库 与窗体的交互(CAD—C#二次开发入门)

第一步&#xff1a;搭建CAD类库dll开发环境。 第二步&#xff1a;添加窗体 第三步&#xff1a;添加控件 第四步&#xff1a;双击控件&#xff0c;在控件点击方法内输入代码 第五步&#xff1a;在主程序内实例化新建的form类&#xff0c;并弹窗form窗体 第六步&#xff1a;CAD命…

第五届人工智能与教育国际学术会议(ICAIE 2024)

文章目录 一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询 一、会议详情 二、重要信息 大会官网&#xff1a;https://ais.cn/u/vEbMBz提交检索&#xff1a;EI Compendex、IEEE Xplore、Scopus 三、大会介绍 第五届人工智能与教育国际学术会议&#x…

学习虚幻C++开发日志——TSet

TSet 官方文档&#xff1a;虚幻引擎中的Set容器 | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com) TSet 是通过对元素求值的可覆盖函数&#xff0c;使用数据值本身作为键&#xff0c;而不是将数据值与独立的键相关联。 默认情况下&#xff0c;TSet 不支持重…

大数据-168 Elasticsearch 单机云服务器部署运行 详细流程

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

基于stm32的4G模块点灯实验

led模块功能封装 #include "led.h" #include "sys.h"//初始化GPIO函数 void led_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOB_CLK_ENABLE();//调用GPIO初始化函数gpio_initstruct.Pin GPIO_PIN_8 | GPIO_PIN_9;gpio_inits…

Linux基本指令一眼看懂(简洁表示)

首先先声明是简单表示&#xff0c;如果要全指令有链接 1. ls 指令 ls [选项] [文件/目录]常用选项: -l: 以长格式列出文件和目录的详细信息。 -a: 显示所有文件&#xff0c;包括隐藏文件&#xff08;以.开头的文件&#xff09;。 -h: 以人类可读的格式显示文件大小。 示例: …

基于stm32的esp8266的WIFI控制风扇实验

实验案例&#xff37;&#xff29;&#xff26;&#xff29;控制风扇 项目需求 电脑通过esp8266模块远程遥控风扇。 项目框图 ​ 风扇模块封装 #include "sys.h" #include "fan.h"void fan_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开时钟…

数据库知识点整理

DDL DDL-数据库操作 show databases ------------ 查看所有数据库 select database(); ----------查看当前数据库 create database 数据库名&#xff1b;---- 创建数据库 use 数据库名&#xff1b; --------------使用数据库 drop database 数据库名&#xff1b;--…