数据结构之顺序结构二叉树(超详解)
文章目录
- 1 树
- 1.1 树的概念与结构
- 1.2 相关术语
- 1.3 树的表示与运用场景
- 1.3.1 运用场景
- 2. 二叉树
- 2.1 概念与结构
- 2.1.1 满二叉树
- 2.1.2 完全二叉树
- 3. 顺序结构二叉树
- 3.1 堆的引入
- 3.1.1 概念与结构
- 3.2 功能实现
- 3.2.1 堆的结构
- 3.2.2 初始化、销毁
- 3.3 堆的插入数据
- 3.3.1 向上调整算法
- 3.4 堆是否为空
- 3.5 删除堆顶数据
- 3.5.1 向下调整算法
- 3.5.2 获取堆顶数据
- 3.5.2.1 求有效数据个数
- 3.6 向上(下)调整算法的复杂度比较
- 3.6.1 向上调整算法时间复杂度
- 3.6.2 向下调整算法时间复杂度
- 4. 代码实现
1 树
1.1 树的概念与结构
树是⼀种非线性的数据结构,它是由 n(n>=0) 个有限结点组成⼀个具有层次关系的集合。
具有以下特点:
- 具有根节点,且根节点无前驱结点。
- 除根结点外,其余结点被分成 M(M>0) 个互不相交的集合,每⼀个集合又是⼀棵结构与树类似的子树。每棵子树的根结点仅有一个前驱结点,但可以有多个互不相交的后驱结点。(若存在相交就是图了)
1.2 相关术语
- 子结点/孩子结点:⼀个结点的子树的根结点称子结点; 如上图:B是A的子结点。
- 父结点/双亲结点:含有子结点的结点称为其子结点的父结点; 如上图:A是B的父结点。
- 结点的度:⼀个结点有几个子结点,度就是多少;如A的度为3,F的度为0。
- 树的度:⼀棵树中,最大的结点的度称为树的度; 如上图:树的度为3。
- 叶子结点/终端结点:度为 0 的结点称为叶结点; 如上图: J、K、L… 等结点为叶结点。
- 分支结点/非终端结点:度不为 0 的结点; 如上图: A、B、C、D… 等结点为分支结点。
- 兄弟结点:具有相同父结点的结点互称为兄弟结点(亲兄弟); 如上图: E、F 是兄弟结点。
- 结点的层次:从根开始定义起,根为第 1 层,根的⼦结点为第 2 层,以此类推。
- 树的高度或深度:树中结点的最大层次; 如上图:树的高度为 4。
- 结点的祖先:从根到该结点所经分支上的所有结点;如上图: A 是所有结点的祖先。
- 子孙:以某结点为根的子树中任⼀结点都称为该结点的子孙。如上图:所有结点都是A的子孙
- 路径:⼀条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列;如A到J的路径为:A-B-E-J。
- 森林:由 m(m>0) 棵互不相交的树的集合称为森林。
1.3 树的表示与运用场景
树的表示有很多种,最常用的便是孩子兄弟表示法,其很好地解决了结点和结点之间的关系。
struct TreeNode
{struct Node* child; // 左边开始的第⼀个孩⼦结点struct Node* brother; // 指向其右边的下⼀个兄弟结点int data; // 结点中的数据域
};
1.3.1 运用场景
文件系统是计算机存储和管理文件的⼀种方式,它利用树形结构来组织和管理文件和文件夹。在文件系统中,树结构被广泛应用,它通过父结点和⼦结点之间的关系来表示不同层级的文件和文件夹之间的关联。
2. 二叉树
2.1 概念与结构
⼀棵二叉树是结点的⼀个有限集合,该集合由⼀个根结点加上两棵别称为左子树和右子树的二叉树组成或者为空。
特点:
- 不存在大于度大于2的结点;
- 二叉树有左右之分,次序不能颠倒。
2.1.1 满二叉树
如果每⼀个层的结点数都达到最大值或满足结点总数是2k-1则这个二叉树就是满二叉树。
2k-1的公式推导:
总的结点数:20 + 21 + 22+……+2k-1 = 1 * (1 - 2k) / 1 - 2 = 2k-1
2.1.2 完全二叉树
规定根结点的层数为 1:
- ⼀棵非空二叉树的第i层上最多有 2i−1 个结点
- 深度为 h 的二叉树的最大结点数是 2h − 1
- 具有 n 个结点的满二叉树的深度 h = log2 (n + 1) ( log以2为底, n+1 为对数) -->满二叉树是特殊的完全二叉树。
3. 顺序结构二叉树
顺序结构存储是使用数组来存储,在实现完全二叉树能减少空间浪费。
3.1 堆的引入
3.1.1 概念与结构
- 对于序号i对应的结点,若i>0,则(i-1)/2为父结点;若i=0,则无父结点;
- 若2*i+1<n,则对应其左孩子;
- 若2*i+2<n,则对应其右孩子。
3.2 功能实现
3.2.1 堆的结构
由于堆底层是用数组实现的,因此相似于顺序表,其结构定义如下:
typedef int HPDataType;
//定义堆的结构
typedef struct HeapNode
{HPDataType* arr;int size;//有效数据个数int capacity;//容量
}HP;
3.2.2 初始化、销毁
这些代码实现已经在顺序表中介绍到。
//堆的初始化
void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = php->capacity = 0;
}
//堆的销毁
void HPDesTroy(HP* php)
{assert(php);if (php->arr)free(php->arr);php->arr = NULL;php->capacity = php->size = 0;
}
3.3 堆的插入数据
熟悉了堆的概念与结构后,我们清楚堆要不就是大根堆,要不就是小根堆。问题在于插入数据后,我们如何通过代码实现化成大根堆或者小根堆的形式?由此我们提出了向上(下)调整算法,也会带大家分析这两种算法哪种更好。
3.3.1 向上调整算法
3.4 堆是否为空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
3.5 删除堆顶数据
- 在删除堆顶数据时,先要判断堆是否为空,因此采用assert。
- 删除堆顶数据后,如何让其再次成为大(小)根堆。
由此我们引入了向下调整算法。
3.5.1 向下调整算法
前提:左右⼦树必须是⼀个堆,才能调整。
3.5.2 获取堆顶数据
HPDataType HPTop(HP* php)
{assert(!HPEmpty(php));return php->arr[0];
}
3.5.2.1 求有效数据个数
int HPSize(HP* php)
{assert(php);return php->size;
}
3.6 向上(下)调整算法的复杂度比较
3.6.1 向上调整算法时间复杂度
根据大O表示法,则O(n*log2n) --> 详见算法复杂度篇章
3.6.2 向下调整算法时间复杂度
根据大O表示法可见时间复杂度为O(n)
因此==向下调整算法的时间复杂度更优==。
4. 代码实现
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<time.h>typedef int HPDataType;
//定义堆的结构
typedef struct HeapNode
{HPDataType* arr;int size;//有效数据个数int capacity;//容量
}HP;//堆的初始化
void HPInit(HP* php);
//堆的销毁
void HPDesTroy(HP* php);
//堆的插入数据
void HPPush(HP* php, HPDataType x);
//删除堆顶数据
void HPPop(HP* php);
//获取堆顶数据
HPDataType HPTop(HP* php);
//判空
bool HPEmpty(HP* php);
//求size
int HPSize(HP* php);//向上调整
void AdjustUp(HPDataType* arr, int child);
//向下调整
void AdjustDown(HPDataType* arr, int parent, int n);
//交换
void Swap(int* x, int* y);
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"//堆的初始化
void HPInit(HP* php)
{assert(php);php->arr = NULL;php->size = php->capacity = 0;
}
//堆的销毁
void HPDesTroy(HP* php)
{assert(php);if (php->arr)free(php->arr);php->arr = NULL;php->capacity = php->size = 0;
}
//交换
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
//向上调整
void AdjustUp(HPDataType* arr, int child)
{int parent = (child - 1) / 2;while (child > 0){//>:大堆//<:小堆if (arr[child] > arr[parent]){//交换Swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}else {break;}}
}
//堆的插入数据
void HPPush(HP* php, HPDataType x)
{assert(php);//判断空间是否不足if (php->size == php->capacity){int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;//空间不足需要增容HPDataType* tmp = (HPDataType*)realloc(php->arr, sizeof(HPDataType) * newCapacity);if (tmp == NULL){perror("realloc fail!");exit(1);}//realloc成功php->arr = tmp;php->capacity = newCapacity;}php->arr[php->size] = x;//向上调整AdjustUp(php->arr, php->size - 1);php->size++;
}//向下调整
void AdjustDown(HPDataType* arr, int parent, int n)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}//>建小堆//<建大堆if (arr[parent] < arr[child]){Swap(&arr[parent], &arr[child]);parent = child;child = parent * 2 + 1;}else {break;}}
}
//删除堆顶数据
void HPPop(HP* php)
{assert(!HPEmpty(php));Swap(&php->arr[0], &php->arr[php->size - 1]);php->size--;//向下调整AdjustDown(php->arr, 0, php->size);
}
//获取堆顶数据
HPDataType HPTop(HP* php)
{assert(!HPEmpty(php));return php->arr[0];
}
//判空
bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}
//求size
int HPSize(HP* php)
{assert(php);return php->size;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"void test()
{HP hp;HPInit(&hp);HPPush(&hp, 1);HPPush(&hp, 3);HPPush(&hp, 2);HPPush(&hp, 4);/*HPPop(&hp);HPPop(&hp);HPPop(&hp);HPPop(&hp);*/while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));HPPop(&hp);}HPDesTroy(&hp);
}void test01()
{int arr[] = { 14,51,31,21,23,32 };int n = sizeof(arr) / sizeof(arr[0]);HP hp;HPInit(&hp);//调用push将数组中的数据建堆for (int i = 0;i < n;i++){HPPush(&hp, arr[i]);}int i = 0;while (!HPEmpty(&hp)){arr[i++] = HPTop(&hp);HPPop(&hp);}for (int i = 0;i < n;i++){printf("%d ", arr[i]);}HPDesTroy(&hp);
}int main()
{test();test01();//int arr[] = { 14,51,31,21,23,32 };//int n = sizeof(arr) / sizeof(arr[0]);Bubblesort(arr,n);//HeapSort(arr,n);//for (int i = 0;i < n;i++)//{// printf("%d ", arr[i]);//}//CreateDate();TopK();return 0;
}
相关文章:
数据结构之顺序结构二叉树(超详解)
文章目录 1 树1.1 树的概念与结构1.2 相关术语1.3 树的表示与运用场景1.3.1 运用场景 2. 二叉树2.1 概念与结构2.1.1 满二叉树2.1.2 完全二叉树 3. 顺序结构二叉树3.1 堆的引入3.1.1 概念与结构 3.2 功能实现3.2.1 堆的结构3.2.2 初始化、销毁 3.3 堆的插入数据3.3.1 向上调整算…...
acwing_5722_十滴水
acwing_5722_十滴水 下面这篇大佬的题解属实是把指针用明白了,可以好好理解一下: 原题解连接:AcWing 5722. 一个简单模拟实现 - AcWing map/unordered_map的用法:见收藏夹 #include<iostream> #include<unordered_map> #incl…...
acwing-3194 最大的矩形
acwing-3194 最大的矩形 这个题程序设计课上有讲过, 平民算法,时间复杂度在 O ( n 2 ) O(n^2) O(n2) // // Created by HUAWEI on 2024/10/28. // #include<iostream>using namespace std;const int Max_size 1e4 20;int N; int h[Max_size];…...
UnityDemo-TheBrave-制作笔记
这是我跟着b站up主MStudio的视频学习制作的,大体上没有去做一些更新的东西,这里只是一个总的总结。在文章的最后,我会放上可以游玩该游戏的链接和exe可执行文件,不过没有对游戏内容进行什么加工,只有基本的功能实现罢了…...
玩转 JMeter:Random Order Controller让测试“乱”出花样
嘿,各位性能测试的小伙伴们!今天咱要来唠唠 JMeter 里超级有趣又超实用的 Random Order Controller(随机顺序控制器),它就像是性能测试这场大戏里的“魔术棒”,轻轻一挥,就能让测试场景变得千变…...
VTK知识学习(33)-交互问题2
1、前言 主要是针对前面有过实现不了交互的情况进行说明,经过一些尝试和分析调用API,总算实现RenderWindowControl函数回调正常串接,当然这个移动处理事件的效果目前也没有确认。 2、使用 vtkImageReslice reslice vtkImageReslice.New();p…...
Centos9-SSH免密登录配置-修改22端口-关闭密码登录-提高安全性
Centos9-SSH免密登录配置-修改22端口-关闭密码登录 生成秘钥对将公钥信息存进authorized_keys测试登录查询访问记录、比对指纹更换22访问端口关闭账号密码登录生成秘钥对 生成密钥对,指定 备注 和 文件目录命令执行后,默认两次回车,不设置秘钥使用密码ssh-keygen -t rsa -b …...
SqlServer: An expression services limit has been reached异常处理
在工作中遇到一个问题,因为项目很老,代码很不规范,出现一种场景: 查询所有客户(5w条以上),然后根据客户Id,再去其他表查询,代码中是直接将customerId拼接到sql中去查询,形成的sql如…...
CentOS下安装Docker
Docker 必须要在Linux环境下才能运行,windows下运行也是安装虚拟机后才能下载安装运行,菜鸟教程 下载安装 linux 依次执行下边步骤 更新 yum yum update 卸载旧的Docker yum remove docker docker-client docker-client-latest docker-common doc…...
WPF控件Grid的布局和C1FlexGrid的多选应用
使用 Grid.Column和Grid.Row布局,将多个C1FlexGrid布局其中,使用各种事件来达到所需效果,点击复选框可以加载数据到列表,移除列表的数据,自动取消复选框等 移除复选框的要注意!!!&am…...
Jenkins-持续集成、交付、构建、部署、测试
Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二:Jenkins 版本三:DevOps流程简述1> 持续集成(Continuous Integration,CI࿰…...
高级第一次作业
1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下大于10M的文件转移到…...
Copula算法原理和R语言股市收益率相依性可视化分析
阅读全文:http://tecdat.cn/?p6193 copula是将多变量分布函数与其边缘分布函数耦合的函数,通常称为边缘。在本视频中,我们通过可视化的方式直观地介绍了Copula函数,并通过R软件应用于金融时间序列数据来理解它(点击文…...
反弹SHELL不回显带外正反向连接防火墙出入站文件下载
什么是反弹shell 正向连接正向连接(Forward Connection):正向连接是一种常见的网络通信模式,其中客户端主动发起连接到服务器或目标系统。正向连接通常用于客户端-服务器通信,客户端主动请求服务或资源,例如…...
后盾人JS--JS值类型使用
章节介绍与类型判断 看看构造函数 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</t…...
1月11日
[WUSTCTF2020]CV Maker 可以看到有个注册页面,尝试注册一个用户登进去看看 进来后第一眼就看到文件上传,尝试上传,上传php后返回了 文件上传后端检测exif_imagetype()函数 他提示不是image,也就是需要我们构造一个文件头为图像类…...
【深度学习】Pytorch:加载自定义数据集
本教程将使用 flower_photos 数据集演示如何在 PyTorch 中加载和导入自定义数据集。该数据集包含不同花种的图像,每种花的图像存储在以花名命名的子文件夹中。我们将深入讲解每个函数和对象的使用方法,使读者能够推广应用到其他数据集任务中。 flower_ph…...
最近在盘gitlab.0.先review了一下docker
# 正文 本猿所在产品的代码是保存到了一个本地gitlab实例上,实例是别的同事搭建的。最近又又又想了解一下,而且已经盘了一些了,所以写写记录一下。因为这个事儿没太多的进度压力,索性写到哪儿算哪儿,只要是新了解到的…...
OA项目登录
导入依赖,下面的依赖是在这次OA登录中用到的 <!--web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.sprin…...
verilogHDL仿真详解
前言 Verilog HDL中提供了丰富的系统任务和系统函数,用于对仿真环境、文件操作、时间控制等进行操作。(后续会进行补充) 正文 一、verilogHDL仿真详解 timescale 1ns/1ps //时间单位为1ns,精度为1ps, //编译…...
基于http协议的天气爬虫
该系统将基于目前比较流行的网络爬虫技术, 对网站上的天气数据进行查询分析, 最终使客户能够通过简单的操作, 快速, 准确的获取目标天气数据。主要包括两部分的功能, 第一部分是天气数据查询, 包括时间段数…...
_STM32关于CPU超频的参考_HAL
MCU: STM32F407VET6 官方最高稳定频率:168MHz 工具:STM32CubeMX 本篇仅仅只是提供超频(默认指的是主频)的简单方法,并未涉及STM32超频极限等问题。原理很简单,通过设置锁相环的倍频系数达到不同的频率&am…...
C#,图论与图算法,任意一对节点之间最短距离的弗洛伊德·沃肖尔(Floyd Warshall)算法与源程序
一、弗洛伊德沃肖尔算法 Floyd-Warshall算法是图的最短路径算法。与Bellman-Ford算法或Dijkstra算法一样,它计算图中的最短路径。然而,Bellman Ford和Dijkstra都是单源最短路径算法。这意味着他们只计算来自单个源的最短路径。另一方面,Floy…...
AWS云计算概览(自用留存,整理中)
目录 一、云概念概览 (1)云计算简介 (2)云计算6大优势 (3)web服务 (4)AWS云采用框架(AWS CAF) 二、云经济学 & 账单 (1)定…...
1. npm 常用命令详解
npm 常用命令详解 npm(Node Package Manager)是 Node.js 的包管理工具,用于安装和管理 Node.js 应用中的依赖库。下面是 npm 的一些常用命令及其详细解释和示例代码。 镜像源 # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 …...
js:根据后端返回数据的最大值进行计算然后设置这个最大值为百分之百,其他的值除这个最大值
问: 现在tabData.value 接收到了后端返回的数据, [{text:人力,percentage:‘90’},{text:物品,percentage:‘20’},{text:物理,percentage:‘50’},{text:服务,percentageÿ…...
【Spring】@Size 无法拦截null的原因
问题复现 在构建 Web 服务时,我们一般都会对一个 HTTP 请求的 Body 内容进行校验,例如我们来看这样一个案例及对应代码。当开发一个学籍管理系统时,我们会提供了一个 API 接口去添加学生的相关信息,其对象定义参考下面的代码&…...
【Block总结】掩码窗口自注意力 (M-WSA)
摘要 论文链接:https://arxiv.org/pdf/2404.07846 论文标题:Transformer-Based Blind-Spot Network for Self-Supervised Image Denoising Masked Window-Based Self-Attention (M-WSA) 是一种新颖的自注意力机制,旨在解决传统自注意力方法在…...
用 HTML5 Canvas 和 JavaScript 实现雪花飘落特效
这篇文章将带您深入解析使用 HTML5 Canvas 和 JavaScript 实现动态雪花特效的代码原理。 1,效果展示 该效果模拟了雪花从天而降的动态场景,具有以下特点: 雪花数量、大小、透明度和下落速度随机。雪花会在屏幕底部重置到顶部,形成循环效果。随窗口大小动态调整,始终覆盖…...
【cocos creator】【ts】事件派发系统
触发使用: EventTool.emit(“onClick”) 需要监听的地方,onload调用: EventTool.on(“onClick”, this.onClickEvent, this) /**事件派发*/class EventTool {protected static _instance: EventTool null;public static get Instance(): Eve…...
个人网站制作总体设计/热搜榜上2023年热搜
首先,看一下前端工程师的核心技能有:• HTML编写网页结构• CSS美化页面盒子模型,布局方式(flexbox,grid)• JavaScript事件,交互,数据处理基础语法,ES新规范• 网络基础…...
禹州市5g网站基础建设/优化大师电脑版下载
目录 1、包的定义 2、包的导入 3、系统常见包 4、总结 以下讲解的内容,概念清除即可,实际上现在使用的IDE开发工具,很多操作不需要我们手动去完成了。 1、包的定义 任何操作系统中,都有一个统一的共识:同一个目录…...
南昌市网络开发公司/seo入门培训班
数据采集高并发框架同时, Cascading框架开发背后的企业面貌,已经在第一轮风险投资中获得了400万美元的投资。 该公司由Cascading的作者Chris Wensel于2008年创立,是第一批成立初创公司的公司,旨在应对开发大数据应用程序的复杂性。…...
国内优秀企业网站设计/线上推广外包公司
如何考虑线程池: CPU密集型: cpu的核数1个线程的线程池:减少上下文的切换 IO密集型: 当出现大量的IO阻塞的时候...
重庆科技网站建设/数字营销策划
一.先创建一个小表(test_01)进行测试(主节点IP:169.254.109.130/oracle服务器IP:169.254.109.100) 1.测试连接oracle; sqoop list-tables --connect jdbc:oracle:thin:169.254.109.100/ciicods --username odsuser --password odsuser 2.创建HDFS目录; sudo -u …...
网站报纸什么软件做/东莞网站建设优化诊断
B类网路子网掩码是225.255.224.0,那子网个数是多少? 首先将子网掩码划分成二进制如下 1111 1111 .1111 1111 .1100 0000 .0000 0000 在根据 下图B类网路的地址的划分知道网络地址应该是16位, 上题目地址是18位,所以之类主机为因该是8-2位,出去全0和全1的…...