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

数据结构之顺序结构二叉树(超详解)

在这里插入图片描述


在这里插入图片描述


文章目录

  • 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) 个有限结点组成⼀个具有层次关系的集合。
具有以下特点:

  1. 有根节点,且根节点无前驱结点
  2. 除根结点外,其余结点被分成 M(M>0) 个互不相交的集合,每⼀个集合又是⼀棵结构与树类似的子树。每棵子树的根结点仅有一个前驱结点,但可以有多个互不相交的后驱结点。(若存在相交就是图了)
    在这里插入图片描述

1.2 相关术语

  1. 子结点/孩子结点:⼀个结点的子树的根结点称子结点; 如上图:B是A的子结点。
  2. 父结点/双亲结点:含有子结点的结点称为其子结点的父结点; 如上图:A是B的父结点。
  3. 结点的度:⼀个结点有几个子结点,度就是多少;如A的度为3,F的度为0。
  4. 树的度:⼀棵树中,最大的结点的度称为树的度; 如上图:树的度为3。
  5. 叶子结点/终端结点:度为 0 的结点称为叶结点; 如上图: J、K、L… 等结点为叶结点。
  6. 分支结点/非终端结点:度不为 0 的结点; 如上图: A、B、C、D… 等结点为分支结点。
  7. 兄弟结点:具有相同父结点的结点互称为兄弟结点(亲兄弟); 如上图: E、F 是兄弟结点。
  8. 结点的层次:从根开始定义起,根为第 1 层,根的⼦结点为第 2 层,以此类推。
  9. 树的高度或深度:树中结点的最大层次; 如上图:树的高度为 4。
  10. 结点的祖先:从根到该结点所经分支上的所有结点;如上图: A 是所有结点的祖先。
  11. 子孙:以某结点为根的子树中任⼀结点都称为该结点的子孙。如上图:所有结点都是A的子孙
  12. 路径:⼀条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列;如A到J的路径为:A-B-E-J。
  13. 森林:由 m(m>0) 棵互不相交的树的集合称为森林。

1.3 树的表示与运用场景

树的表示有很多种,最常用的便是孩子兄弟表示法,其很好地解决了结点和结点之间的关系。

struct TreeNode
{struct Node* child; // 左边开始的第⼀个孩⼦结点struct Node* brother; // 指向其右边的下⼀个兄弟结点int data; // 结点中的数据域
};

在这里插入图片描述

1.3.1 运用场景

文件系统是计算机存储和管理文件的⼀种方式,它利用树形结构来组织和管理文件和文件夹。在文件系统中,树结构被广泛应用,它通过父结点和⼦结点之间的关系来表示不同层级的文件和文件夹之间的关联。
在这里插入图片描述

2. 二叉树

2.1 概念与结构

⼀棵二叉树是结点的⼀个有限集合,该集合由⼀个根结点加上两棵别称为左子树和右子树的二叉树组成或者为空。
在这里插入图片描述
特点:

  1. 不存在大于度大于2的结点
  2. 二叉树有左右之分,次序不能颠倒

2.1.1 满二叉树

如果每⼀个层的结点数都达到最大值或满足结点总数是2k-1则这个二叉树就是满二叉树
2k-1的公式推导:
在这里插入图片描述
总的结点数:20 + 21 + 22+……+2k-1 = 1 * (1 - 2k) / 1 - 2 = 2k-1

2.1.2 完全二叉树

规定根结点的层数为 1:

  1. ⼀棵非空二叉树的第i层上最多有 2i−1 个结点
  2. 深度为 h 的二叉树的最大结点数是 2h − 1
  3. 具有 n 个结点的满二叉树的深度 h = log2 (n + 1) ( log以2为底, n+1 为对数) -->满二叉树是特殊的完全二叉树。

3. 顺序结构二叉树

顺序结构存储是使用数组来存储,在实现完全二叉树能减少空间浪费。
在这里插入图片描述

3.1 堆的引入

3.1.1 概念与结构

在这里插入图片描述

在这里插入图片描述

  1. 对于序号i对应的结点,若i>0,则(i-1)/2为父结点;若i=0,则无父结点;
  2. 若2*i+1<n,则对应其左孩子;
  3. 若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 删除堆顶数据

  1. 在删除堆顶数据时,先要判断堆是否为空,因此采用assert。
  2. 删除堆顶数据后,如何让其再次成为大(小)根堆。
    在这里插入图片描述
    由此我们引入了向下调整算法。

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. 代码实现

Heap.h
#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);
Heap.c
#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;
}
test.c
#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_十滴水 下面这篇大佬的题解属实是把指针用明白了&#xff0c;可以好好理解一下&#xff1a; 原题解连接&#xff1a;AcWing 5722. 一个简单模拟实现 - AcWing map/unordered_map的用法:见收藏夹 #include<iostream> #include<unordered_map> #incl…...

acwing-3194 最大的矩形

acwing-3194 最大的矩形 这个题程序设计课上有讲过&#xff0c; 平民算法&#xff0c;时间复杂度在 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的视频学习制作的&#xff0c;大体上没有去做一些更新的东西&#xff0c;这里只是一个总的总结。在文章的最后&#xff0c;我会放上可以游玩该游戏的链接和exe可执行文件&#xff0c;不过没有对游戏内容进行什么加工&#xff0c;只有基本的功能实现罢了…...

玩转 JMeter:Random Order Controller让测试“乱”出花样

嘿&#xff0c;各位性能测试的小伙伴们&#xff01;今天咱要来唠唠 JMeter 里超级有趣又超实用的 Random Order Controller&#xff08;随机顺序控制器&#xff09;&#xff0c;它就像是性能测试这场大戏里的“魔术棒”&#xff0c;轻轻一挥&#xff0c;就能让测试场景变得千变…...

VTK知识学习(33)-交互问题2

1、前言 主要是针对前面有过实现不了交互的情况进行说明&#xff0c;经过一些尝试和分析调用API&#xff0c;总算实现RenderWindowControl函数回调正常串接&#xff0c;当然这个移动处理事件的效果目前也没有确认。 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异常处理

在工作中遇到一个问题&#xff0c;因为项目很老&#xff0c;代码很不规范&#xff0c;出现一种场景&#xff1a; 查询所有客户(5w条以上)&#xff0c;然后根据客户Id&#xff0c;再去其他表查询&#xff0c;代码中是直接将customerId拼接到sql中去查询&#xff0c;形成的sql如…...

CentOS下安装Docker

Docker 必须要在Linux环境下才能运行&#xff0c;windows下运行也是安装虚拟机后才能下载安装运行&#xff0c;菜鸟教程 下载安装 linux 依次执行下边步骤 更新 yum yum update 卸载旧的Docker yum remove docker docker-client docker-client-latest docker-common doc…...

WPF控件Grid的布局和C1FlexGrid的多选应用

使用 Grid.Column和Grid.Row布局&#xff0c;将多个C1FlexGrid布局其中&#xff0c;使用各种事件来达到所需效果&#xff0c;点击复选框可以加载数据到列表&#xff0c;移除列表的数据&#xff0c;自动取消复选框等 移除复选框的要注意&#xff01;&#xff01;&#xff01;&am…...

Jenkins-持续集成、交付、构建、部署、测试

Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二&#xff1a;Jenkins 版本三&#xff1a;DevOps流程简述1> 持续集成&#xff08;Continuous Integration&#xff0c;CI&#xff0…...

高级第一次作业

1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下大于10M的文件转移到…...

Copula算法原理和R语言股市收益率相依性可视化分析

阅读全文&#xff1a;http://tecdat.cn/?p6193 copula是将多变量分布函数与其边缘分布函数耦合的函数&#xff0c;通常称为边缘。在本视频中&#xff0c;我们通过可视化的方式直观地介绍了Copula函数&#xff0c;并通过R软件应用于金融时间序列数据来理解它&#xff08;点击文…...

反弹SHELL不回显带外正反向连接防火墙出入站文件下载

什么是反弹shell 正向连接正向连接&#xff08;Forward Connection&#xff09;&#xff1a;正向连接是一种常见的网络通信模式&#xff0c;其中客户端主动发起连接到服务器或目标系统。正向连接通常用于客户端-服务器通信&#xff0c;客户端主动请求服务或资源&#xff0c;例如…...

后盾人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 可以看到有个注册页面&#xff0c;尝试注册一个用户登进去看看 进来后第一眼就看到文件上传&#xff0c;尝试上传&#xff0c;上传php后返回了 文件上传后端检测exif_imagetype()函数 他提示不是image&#xff0c;也就是需要我们构造一个文件头为图像类…...

【深度学习】Pytorch:加载自定义数据集

本教程将使用 flower_photos 数据集演示如何在 PyTorch 中加载和导入自定义数据集。该数据集包含不同花种的图像&#xff0c;每种花的图像存储在以花名命名的子文件夹中。我们将深入讲解每个函数和对象的使用方法&#xff0c;使读者能够推广应用到其他数据集任务中。 flower_ph…...

最近在盘gitlab.0.先review了一下docker

# 正文 本猿所在产品的代码是保存到了一个本地gitlab实例上&#xff0c;实例是别的同事搭建的。最近又又又想了解一下&#xff0c;而且已经盘了一些了&#xff0c;所以写写记录一下。因为这个事儿没太多的进度压力&#xff0c;索性写到哪儿算哪儿&#xff0c;只要是新了解到的…...

OA项目登录

导入依赖,下面的依赖是在这次OA登录中用到的 <!--web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.sprin…...

verilogHDL仿真详解

前言 Verilog HDL中提供了丰富的系统任务和系统函数&#xff0c;用于对仿真环境、文件操作、时间控制等进行操作。&#xff08;后续会进行补充&#xff09; 正文 一、verilogHDL仿真详解 timescale 1ns/1ps //时间单位为1ns&#xff0c;精度为1ps&#xff0c; //编译…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...