[数据结构]树

news/2025/2/27 14:21:33/文章来源:https://www.cnblogs.com/rikkkkka/p/18740874

树(基础)

1 定义

1.1 树是什么

树是一种数据结构,因为形似倒着的树而得名. 树是一种特殊图

1.2 树的定义

递归定义

1.2.1 有根树的定义

形象化的,如图1,有根树存在根节点这一定义,从根节点可以分出任意个分支,这任意个分支又可以继续细分,分出的节点称为“子节点”。


抽象化的,树也是$N$个节点和$N-1$条边的集合。


每条边都将某个节点连接至他的父亲,而除去根节点外的每个节点都有父亲,每个结点之间互不相交。

1.2.2 无根树的定义

形象化的,无根树就是有根树删去根节点后得到的东西


抽象化的,无根树也是树是$N$个节点和$N-1$条边的集合。


每条边都将某个节点连接至他的父亲,每个节点互不相交

图1 有根树

1.3 有关树的一些常用术语

森林:每个连通块都是树的图。按照定义,一棵树也是森林


叶节点:没有子节点的节点


父亲:一个节点上一层的点


祖先:一个点上层的每一个点


子节点:一个节点延伸出的下一个节点


深度:一个点到根节点的层数(边数)


高度:从叶节点到根节点的层数。


兄弟:同一个父节点的子节点互为兄弟


后代:一个点下层的每一个点是当前点的后代。


:一个节点的子树个数 一个节点生的子节点的个数(其实这个概念应该放在前面,大家可以试着使用度来概括一些前期概念)


内部节点:根以外的分支节点


树的度:这棵树各节点中度的最大值


图2 数的术语

1.4 特殊树

:满足与任意节点相连的边不超过2条的树


二叉树:每个节点最多只有两个子节点的树。


完整二叉树:每个节点的子节点数量都为2没有


完全二叉树:只有最下面两层节点度数可以$<2$,且最下面一层节点都位于该层最左边的位置上。


完美二叉树:所有叶节点深度相同,且所有节点都只有两个子节点!


注意!完美二叉树一定也是完全二叉树和完满二叉树,但完满二叉树不一定是完全二叉树和完美二叉树。





1.5 二叉树的一些性质

性质部分:

1.在二叉树的第$i$层上最多有$2^{i-1}$个节点

2.深度为$k$的二叉树最多有$2^k-1$个节点

3.对任意一棵二叉树,如果其叶节点数为$n_0$,度为$2$的节点数为$n_2$,则一定满足$n_0=n_2+1$

4.具有$n$个节点的完全二叉树的深度为$floor(log_2n)+1$

5.对于一棵$n$个节点的完全二叉树,对任意一个节点$i$,有:


5.1 如果$i=1$,则节点$i$为根,无父节点;

5.2 如果$i>1$,则其父节点编号为$i/2$

5.3 如果$2i>n$,则节点$i$是叶节点,否则左孩子编号为$2i$

5.4 如果$2i+1>n$,则节点$i$无右孩子,否则右孩子编号为$2i+1$



证明部分:

用归纳法证明性质$1$.

当$i=1$时,$2{i-1}$显然成立,现在假设第$i-1$层时命题成立,即第$i-1$层上最多有$2$个节点。由于二叉树的每个节点的度做多为$2$,故在第$i$层上的最大节点数为第$i-1$层的$2$倍,即$2*2{i-2}=2$

2 树的储存

2.1 普通树的储存

2.1.1 顺序存储

1.父亲表示法(数组记录孩子的父亲为父亲)

int data[N];//存数据的
int father[N];//father[i]=j 表示i的父亲为j

2.孩子表示法(数组记录父亲的第任意个孩子为孩子)

int data[N];//不做过多解释
int son[N][M];//son[i][j]=k表示父亲i的第j个孩子为k

3.父亲孩子表示法(双向奔赴的爱)

int data[N];//不做过多解释
int father[N];//father[i]=j 表示i的父亲为j
int son[N][M];//son[i][j]=k表示父亲i的第j个孩子为k

4.孩子兄弟表示法(见故事)

int data[N];//不做过多解释
int firstson[N];//表示父亲的第一个孩子
int nxt[N];//nxt[i]=j表示i的下一个兄弟为j

这里我们老师给我们讲了个故事,说乾隆生了100多个孩子,这时候怎么记是不是自己孩子呢?就让哥哥记住自己弟弟,弟弟在记住自己弟弟,这就是孩子兄弟表示法。

2.1.2 链式存储

1.父亲表示法

struct node
{int data;// 节点存储的数据node *father// 指向父节点的指针
}tree[N];//树

2.孩子表示法

struct node
{int data;// 节点存储的数据node *son[M];//指向子节点的指针
}tree[N];

3.父亲孩子表示法

struct node
{int data;//数据node *father;//指向父亲node *son[M];//指向孩子
}tree[N];

4.孩子兄弟表示法

struct node
{int data;//数据node *firstson;//第一个儿子node *bro;//下一个兄弟
}tree[N];

2.2 二叉树的存储

1.顺序存储

int data[N];//数据域

2.链式存储

struct node
{int data;node *lc;//左孩子node *rc;//右孩子node(int d)//构造函数{data=d;// 初始化节点数据为传入的参数dlc=NULL;// 初始化左子节点指针为NULLrc=NULL;// 初始化右子节点指针为NULL}//另一种写法/*node(int d) : data(d), lc(NULL), rc(NULL){}*/
};
node *bt;//根节点指针

3.树的遍历

先序遍历,中序遍历,后序遍历

3.1 先序遍历

如图8,先序遍历类似$DFS$,从根开始,然后是左子树,递归到最深层后返回,然后遍历右子树,最后回到根



void preoder(int f)
{cout<<data[f]<<" ";//首先在函数运行前输出是为了先从根节点开始if(lc[2*f]>0)//左子树preoder(2*f);if(rc[2*f+1]>0)//右子树preoder(2*f+1);
}

3.2 中序遍历

如图9,中序遍历在遍历完左子树后直接跳向根节点后遍历右子树



void inoder(int f)
{if(lc[f]>0)inoder(lc[f]);cout<<data[f]<<endl;//在遍历左子树时输出是为了先从左子树开始if(rc[f]>0)inoder(rc[f]);
}

3.3 后序遍历

如图10,后序遍历在遍历完左子树后直接跳向右子树叶子节点后向上遍历至根节点



void postoder(int f)
{if(lc[f]>0)postoder(lc[f])if(rc[f]>0)postoder(rc[f]);cout<<data[f]<<endl;//在遍历右子树时输出是为了从右子树开始
}

3.4 FAQ

肯定会有彭于晏有疑问,为什么他们的输出位置不同,决定了他们的遍历次数不同?

1.先序遍历 首先在函数运行前输出是为了先从根节点开始

2.中序遍历 在遍历左子树时输出是为了先从左子树开始

3.后序遍历 在遍历右子树时输出是为了从右子树开始

神不神奇?反正我觉得挺神奇

接下来需要完善的:

2.二叉树性质 证明

4.反推

5.BFS

6.Morris

呼~~ 用时7个多小时终于写完了!希望能帮到你喵~~

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

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

相关文章

StrokesPlus【电脑鼠标键盘手势软件】v0.5.8.0 中文绿色便携版

点击上方蓝字关注我 前言 StrokesPlus.net是一个超方便的手势识别软件,它能帮你用手势来代替鼠标和键盘操作。用起来既简单又灵活,功能还特别强大。 操作起来非常简单,它有好多实用的功能,比如智能识别你写的字、设定手势操作的区域、模拟鼠标的各种动作、运行脚本、响应窗…

大模型推理主战场:什么才是通信协议标配?

关键词:# DeepSeek ;# SSE ;# WebSocketSSE 和 WebSocket 是什么? 大模型应用出现前的主流网络通信协议是什么? 为什么大模型应用没有沿用 Web 类应用的主流通信协议? 为什么 SSE 和 WebSocket 更适合支持大模型应用? 实时通信协议的技术挑战和应对方案 Whats Next?Dee…

webSocket在.net中的使用案例

前言前面asp.net实现长连接 - chenxizhaolu - 博客园学习了如何在asp.net中实现http长连接,这里继续学习websocket。WebSockets 是一种协议,它能让客户端和服务器之间通过单个长期连接进行无缝通信。与 HTTP 等遵循请求-响应模式的传统网络通信方法不同,WebSockets 引入了全…

SQL SERVER日常运维巡检系列之-性能

前言做好日常巡检是数据库管理和维护的重要步骤,而且需要对每次巡检日期、结果进行登记,同时可能需要出一份巡检报告。本系列旨在解决一些常见的困扰:不知道巡检哪些东西 不知道怎么样便捷体检 机器太多体检麻烦 生成报告困难,无法直观呈现结果 性能是系统好坏的重要指标之…

burpsuite激活

激活burpsuite——教程点击Start 文件,把三个框都选上点击RUN,会自动启动,复制一下那个证书粘贴刚刚复制的密钥,点击下一个即可这里点击手动激活,复制请求,粘贴到刚刚那个激活程序的:Activation Request 它会自动生成Response,Copy就行到Burpsutie 里面复制一下,然后点…

KBP310-ASEMI整流桥稳定电力的核心担当

KBP310-ASEMI整流桥稳定电力的核心担当编辑:ll 在当今电子科技飞速发展的时代,各类电子设备充斥着我们的生活,从日常使用的手机、电脑,到工业生产中的大型机械,稳定的电力供应都是它们正常运转的基石。而在这背后,有一个常常被忽视却又至关重要的元件 ——KBP310 整流桥。…

GraphQL开发工具选型指南:Apipost高效调试与文档生成实战解析

GraphQL 调试与文档生成:Apipost 如何简化开发流程 GraphQL开发工具选型指南:Apipost高效调试与文档生成实战解析 GraphQL 凭借其灵活的数据查询能力和高效的接口设计,是现代 API 开发的主流选择。根据 State of JS 2022 的调研,GraphQL 在开发者中的采用率已超过 40%,尤其…

大数据在项目管理中的应用:5个预测分析模型+工具

随着信息技术的飞速发展,大数据在各个领域的应用日益广泛,项目管理也不例外。大数据的分析和应用为项目管理带来了新的机遇和挑战,通过预测分析模型和工具,项目管理者可以更好地规划、执行和监控项目,提高项目的成功率和效益。本文将介绍大数据在项目管理中的应用,重点探…

抖音爆火—可爱俏皮的软件卸载提示页面制作

前两天在抖音刷到了一个很可爱的软件卸载页面,鼠标滑动还会变脸,很萌很可爱,所以想着自己也做一个,花了一下午时间总算写了出来,总体效果还可以,哈哈抖音爆火—可爱俏皮的软件卸载提示页面制作前言 ​ 前两天在抖音刷到了一个很可爱的软件卸载页面,鼠标滑动还会变脸,很…

内部类--成员内部类、静态内部类、局部内部类--java进阶day03

1.内部类 内部类分为4种,成员内部类用处不大,静态内部类和局部内部类更是鸡肋,唯有匿名内部类是需要我们重点掌握的1.成员内部类Inter类要访问Outer类的成员可以直接访问,而Outer要访问Inter,就必须创建出Inter对象才可访问案例2.静态内部类3.局部内部类

逆向软件开发--学生管理系统

本次实验目的:训练逆向软件设计与开发能力。 实验内容:找一个已有的项目,阅读分析,找出软件尚存的缺陷,改进其软件做二次开发,并将过程整理成博客。 来源:CSDN上的学生管理系统 链接: https://blog.csdn.net/weixin_74362817/article/details/142308755fromshare=blogd…

对自己独立开发游戏的能力考察~来自入行4年的小菜鸟自查

一直想设计开发一款自己喜欢玩的游戏,加入各种自己想要的元素,但是总感觉自己技术积累不够,这次刚好有空,尝试写一下,看看自己在哪方面比较欠缺,这次主要是为了检测自己独立开发的能力,着重战斗方面的设计,ui是随便弄的,原谅原谅 首先是主场景大地图,实现了地图创建加…