树和二叉树(不用看课程)

1. 树

1.1 树的概念与结构

树是⼀种非线性的数据结构,它是由 n(n>=0) 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树,也就是说它是根朝上,而叶朝下的。

• 有⼀个特殊的结点,称为根结点,根结点没有前驱结点。

• 除根结点外,其余结点被分成 M(M>0) 个互不相交的集合 T1、T2、……、Tm ,其中每⼀个集合 Ti(1 <= i <= m) 又是⼀棵结构与树类似的子树。每棵子树的根结点有且只有⼀个前驱,可以有 0 个或多个后继。因此,树是递归定义的。

 树形结构中,子树之间不能有交集,否则就不是树形结构。

非树形结构:

•  子树是不相交的(如果存在相交就是图了)(除了根节点之外,有其它的集合,这些集合就是树)
除了根结点外,每个结点有且仅有一个父结点
⼀棵N个结点的树有N-1条边

1.2树相关术语

 

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

1.3 树的表示

孩子兄弟表示法:
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。我们这里就简单的了解其中最常用的孩子兄弟表示法。

1.4 树形结构实际运用场景

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

2. 二叉树

2.1 概念与结构

在树形结构中,我们最常用的就是⼆叉树,⼀棵⼆叉树是结点的⼀个有限集合,该集合由⼀个根结点加上两棵别称为左子树和右子树的⼆叉树组成或者为空。二叉树是树形结构的一种,也可以说是对树的结构加以限制形成二叉树。
 
从上图可以看出二叉树具备以下特点:
1. ⼆叉树不存在度大于 2 的结点。(二叉树只存在度为0、1、2的节点)
2. ⼆叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。(这里的有序是指左右孩子是有区分的)
注意:对于任意的二叉树都是由以下几种情况复合而成的。

 

第一个是空树(度为0),第二个叫只有根节点的二叉树,第三个叫做只有左子树的二叉树,第四个叫做只有右子树的二叉树,第五个叫做左右子树都存在的二叉树。

2.2 特殊的二叉树

2.2.1 满二叉树

⼀个二叉树,除了叶子节点外,如果每⼀个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为 K ,且结点总数是 2 k − 1 ,则它就是满二叉树。

2.2.2 完全⼆叉树

完全⼆叉树是效率很高的数据结构,完全二叉树是由满二叉树引出来的。对于深度为 K 的,有 n 个结点的二叉树,当且仅当其每⼀个结点都与深度为K的满二叉树中编号从 1至  n 的结点⼀⼀对应时称 之为完全二叉树。要注意的是满二叉树是⼀种特殊的完全二叉树。
假设二叉树层次为K,除了第K层外,每层结点的个数达到最大结点数,第K层结点个数不一定达到最大节点数。
这种就不是完全二叉树(完全二叉树结点的顺序是从左到右的)。
总结:
满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树。
💡 ⼆叉树性质
根据满二叉树的特点可知:
1)若规定根结点的层数为 1 ,则⼀棵非空二叉树的第i层上最多有 2^i −1 个结点
2)若规定根结点的层数为 1 ,则深度为 的二叉树的最大结点数是 2^h   − 1
3)若规定根结点的层数为 1 ,具有 n 个结点的满⼆叉树的深度 ( log以2为底, n+1 为对数)
(由2^h-1 = n演变而来)

2.3 ⼆叉树存储结构

二叉树⼀般可以使用两种结构存储,⼀种顺序结构,⼀种链式结构。

2.3.1 顺序结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有 空间的浪费,完全二叉树更适合使用顺序结构存储。

现实中我们通常把堆(⼀种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,⼀个是数据结构,⼀个是操作系统中管理内存的⼀块区域分段。

2.3.2 链式结构

二叉树的链式存储结构是指,用链表来表示⼀棵⼆叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链。后面课程学到高阶数据结构如红黑树等会用到三叉链。

 

3. 实现顺序结构二叉树

一般堆使用顺序结构的数组来存储数据,堆是⼀种特殊的二 叉树,具有二叉树的特性的同时,还具备其他的特性。

3.1 堆的概念与结构

堆具有以下性质:
堆中某个结点的值总是不大于或不小于其父结点的值;
堆总是⼀棵完全二叉树。
小堆堆顶是堆最小值
堆堆顶是堆最大值
•  存储在数组中的元素不一定是有序的 
💡 叉树性质
对于具有 n 个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从
0 开始编号,则对于序号为 i 的结点有:
1. i>0 i 位置结点的双亲序号: (i-1)/2 i=0 i 为根结点编号,无双亲结点
2. 2i+1<n ,左孩子序号: 2i+1 2i+1>=n 否则无左孩子
3. 2i+2<n ,右孩子序号: 2i+2 2i+2>=n 否则无右孩子

//定义堆的结构——数组    堆的底层是使用顺序结构数组来实现的
typedef int HPDataType;
typedef struct Heap
{
    HPDataType* arr;
    int size;//有效的数据个数
    int capacity;//空间大小
}HP;

//堆的初始化

void HPInit(HP* php);

堆的销毁
void HPDestroy(HP* php);

堆数据的插入
void HPPush(HP* php, HPDataType x);

//判断链表是否为空

//判断空间是否足够

实现到堆的数据插入之后,不确定是不是真的符合大、小堆存储,这时候就要进行堆的向上调整算法。在这之间,还要用到两个变量交换的函数Add。(只需要比较父结点和左孩子结点,若父结点大于左孩子结点,就交换位置)。

接下来是出堆,而出堆指的就是删除堆顶数据,当我们直接删除堆顶数据时,会导致堆乱套(后一个位置移动到前一个位置处,堆的底层是顺序表),所以不能直接删除堆顶数据。因此,我们必须采取其他的办法。

方法:

最后一个结点的数据和堆顶数据交换,这时让size--;而堆顶数据(交换后为最后一个结点)能直接被删除,而删除后的堆顺序不一定符合大、小堆,所以我们要用到向下调整算法。

//去堆顶
void HPPop(HP* php);

在出堆中,我们必须要保证父结点的值和左右孩子中最小的值去交换(向下调整算法)。

//出堆顶
HPDataType HPTop(HP* php);

//打印元素判断代码是否正确

附源代码: 

Heap.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//定义堆的结构——数组    堆的底层是使用顺序结构数组来实现的
typedef int HPDataType;
typedef struct Heap
{
    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);
//判空
bool HPEmpty(HP* php);
//出堆顶
HPDataType HPTop(HP* php);

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->capacity = php->size = 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)//不需要等于,child只要走到根节点的位置,根节点没有父节点不需要交换
    {
        if (arr[child] < arr[parent])
        {
            Swap(&arr[parent], &arr[child]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
        {
            break;
        }
    }
}
void HPPush(HP* php, HPDataType x)
{
    assert(php);
    //判断空间是否足够
    if (php->capacity == php->size)
    {
        //扩容
        int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
        HPDataType* tmp = (HPDataType*)realloc(php->arr, newCapacity * sizeof(HPDataType));
        if (tmp == NULL)
        {
            perror("realloc fail!");
            exit(1);
        }
        php->arr = tmp;
        php->capacity = newCapacity;
    }
    php->arr[php->size] = x;
    AdjustUp(php->arr, php->size);
    php->size++;
}
void AdjustDown(HPDataType* arr, int parent, int n)
{
    int child = 2 * parent + 1;
    while (child < n)
    {
        //找左右孩子中最小的
        if (child +1 < n && arr[child] > arr[child + 1])
        {
            child++;
        }
        if (arr[parent] > arr[child])
        {
            Swap(&arr[child], &arr[parent]);
            parent = child;
            child = 2 * parent + 1;
        }
        else
        {
            break;
        }
    }
}

void HPPop(HP* php)
{
    assert(php && php->size);
    Swap(&php->arr[0], &php->arr[php->size - 1]);
    --php->size;
    AdjustDown(php->arr, 0, php->size);
}
//判空
bool HPEmpty(HP* php)
{
    assert(php);
    return php->size == 0;
}
HPDataType HPTop(HP* php)
{
    assert(php && php->size);//堆顶的元素不能为空
    return php->arr[0];
}

text.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void text01()
{
    HP hp;
    HPInit(&hp);
    int arr[] = { 17,20,10,13,19,15 };

    for (int i = 0; i < 6; i++)
    {
        HPPush(&hp, arr[i]);
    }
    while (!HPEmpty(&hp))
    {
        printf("%d ", HPTop(&hp));
        HPPop(&hp);
    }
    HPDestroy(&hp);
}
int main()
{
    text01();
    return 0;
}
 

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

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

相关文章

[微信小程序] css 解决纯数字或字母不自动换行的问题、控制文字行数

效果 css 代码 word-break: break-all; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;解释 word-break: break-all; 作用&#xff1a;这个属性允许在单词内部进行换行&#xff0c;即使单词很长也…

FastAPI(七十七)实战开发《在线课程学习系统》接口开发-- 课程编辑和查看评论

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 课程编辑 先来看下课程编辑 1.判断是否登录 2.判断课程是否存在 3.是否有权限&#xff08;只有自己可以修改自己的课程&#xff09; 4.名称是否重复…

7月23日JavaSE学习笔记

异常&#xff1a; 程序中一些程序处理不了的特殊情况 异常类 Exception 继承自 Throwable 类&#xff08;可抛出的&#xff09; Throwable继承树 Error&#xff1a;错误/事故&#xff0c;Java程序无法处理&#xff0c;如 OOM内存溢出错误、内存泄漏...会导出程序崩溃 常见的…

区块链赋能民生大数据,共筑可信共享新生态

一、背景 在信息化浪潮的推动下&#xff0c;政府服务模式正经历着前所未有的变革。民生卡&#xff0c;作为连接政府与民众的桥梁&#xff0c;承载着居民享受多元化公共服务的重任。然而&#xff0c;部门间信息孤岛现象严重制约了服务效率与居民体验的提升。为此&#xff0c;民…

大厂面试官问我:ConcurrentHashMap底层原理?【后端八股文十五:Java集合合集】

本文为【Java集合 合集】初版&#xff0c;后续还会进行优化更新&#xff0c;欢迎大家关注交流~ hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#…

【Golang 面试基础题】每日 5 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

vue3里将table表格中的数据导出为excel

想要实现前端对表格中的数据进行导出&#xff0c;这里推荐使用xlsx这个依赖库实现。 1、安装 pnpm install xlsx 2、使用 import * as XLSX from "xlsx"; 直接在组件里导入XLSX库&#xff0c;然后给表格table通过ref创建响应式数据拿到table实例&#xff0c;将实…

CSS 基础知识

CSS(级联样式表)是设置 Web 内容样式的代码。CSS 基础知识将介绍入门所需的内容。我们将回答以下问题:如何将文本设置为红色?如何使内容显示在(网页)布局中的某个位置?如何用背景图片和颜色装饰我的网页? 什么是CSS? 像HTML一样,CSS不是一种编程语言。它也不是一种标…

拉提查合创5步玩转git工具协作代码开发

1 工具使用场景 开发团队使用git版本管理工具&#xff0c;进行协作代码开发过程中&#xff0c;最常用的场景为&#xff1a; &#xff08;1&#xff09;拉取代码 将git远端仓库最新代码拉取到本地。 &#xff08;2&#xff09;提交代码 将本地新增修改的代码提交至git远端仓库中…

【Django】开源前端库bootstrap,常用

文章目录 下载bootstrap源文件到本地项目引入bootstrap文件 官网&#xff1a;https://www.bootcss.com/V4版本入口&#xff1a;https://v4.bootcss.com/V5版本入口&#xff1a;https://v5.bootcss.com/ 这里使用成熟的V4版本&#xff0c;中文文档地址&#xff1a;https://v4.b…

SpringBoot整合SSE技术详解

Hi &#x1f44b;, Im shy SpringBoot整合SSE技术详解 1. 引言 在现代Web应用中,实时通信变得越来越重要。Server-Sent Events (SSE)是一种允许服务器向客户端推送数据的技术,为实现实时更新提供了一种简单而有效的方法。本文将详细介绍如何在SpringBoot中整合SSE,并探讨S…

Java的四种引用类型

Java的四种引用类型 1. 强引用&#xff08;Strong Reference&#xff09;2. 软引用&#xff08;Soft Reference&#xff09;3. 弱引用&#xff08;Weak Reference&#xff09;4. 虚引用&#xff08;Phantom Reference&#xff09; &#x1f496;The Begin&#x1f496;点点关注…

go-kratos 学习笔记(4) 服务注册与发现 nacos注册

接口实现​ Registry 接口分为两个&#xff0c;Registrar 为实例注册和反注册&#xff0c;Discovery 为服务实例列表获取 type Registrar interface {// 注册实例Register(ctx context.Context, service *ServiceInstance) error// 反注册实例Deregister(ctx context.Context…

大模型算法面试题(十二)

本系列收纳各种大模型面试题及答案。 1、领域模型Continue PreTrain数据如何选取 在领域模型的Continue PreTrain&#xff08;持续预训练&#xff09;过程中&#xff0c;数据选取是一个至关重要的步骤&#xff0c;它直接影响模型在特定领域上的性能和泛化能力。以下是一些关于…

【机器学习】深入理解损失函数(Loss Functions)

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解损失函数(Loss Functions)什么是损失函数?常见损失函数类型1. 均方误差…

OSPF概述

OSPF OSPF属于内部网关路由协议【IGP】 用于单一自治系统【Autonomous System-AS】内决策路由 自治系统【AS】 执行统一路由策略的一组网络设备的组合 OSPF概述 为了适应大型的网络&#xff0c;OSPF在AS内划分多个区域 每个OSPF路由器只维护所在区域的完整的链路状态信息 …

谷粒商城实战笔记-62-商品服务-API-品牌管理-OSS整合测试

文章目录 一&#xff0c;Java中上传文件到阿里云OSS1&#xff0c;整合阿里云OSS2&#xff0c;测试上传文件 二&#xff0c;Java中整合阿里云OSS服务指南引言准备工作1. 注册阿里云账号2. 获取Access Key3. 添加依赖 实现OSS客户端1. 初始化OSSClient2. 创建Bucket3. 上传文件4.…

ElasticSearch(七)— 相关性检索和组合查询

一、 相关性评分 全文检索与数据库查询的一个显著区别&#xff0c; 就是它并不一定会根据查询条件 做完全精确的匹配。除了模糊查询以外&#xff0c;全文检索还会根据查询条件给文档的相关性打分并排序&#xff0c;将那些与查询条件相关性高的文档排在最前面。 相关性( Relev…

Cocos Creator2D游戏开发-(1)初始化设置

初心: 做一款微信或者抖音小游戏,然后发布,对于我来说这是一个新的赛道; 写这些文档的原因,记录一下自己学习过程,下次用的时候方便找 cocos creator版本: 3.8.3 当前小游戏飞机大战教程来源于: 抖音: 禅影 chanying001 源码目录: https://www.kdocs.cn/l/caLr6XCbEfPa 创建一个…

【CN】Argo 持续集成和交付(一)

1.简介 Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo] Kubernetes 原生工具&#xff0c;用于运行工作流程、管理集群以及正确执行 GitOps。 Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别&#xff0c;然后于 2022 年 12 月 6 日转移到毕业成熟度级别。 argoproj.github.i…