首页 > 其他分享 >树(基础)

树(基础)

时间:2025-01-18 21:11:38浏览次数:1  
标签:node 遍历 int 基础 二叉树 data 节点

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 如果\(2*i>n\),则节点\(i\)是叶节点,否则左孩子编号为\(2*i\)

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



证明部分:

用归纳法证明性质1.

当\(i=1\)时,

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;// 初始化节点数据为传入的参数d
        lc=NULL;// 初始化左子节点指针为NULL
        rc=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个多小时终于写完了!希望能帮到你喵~~

标签:node,遍历,int,基础,二叉树,data,节点
From: https://www.cnblogs.com/March7thDev/p/18678862

相关文章

  • 嵌入式基础 C语言篇 数组.初阶
    一、基本概念逻辑:一次性定义多个相同类型的变量,并存储到一片连续的内存中语法释义:intbuf[5];buf是数组名,即这片连续内存的名称[5]代表这片连续内存总共分成5个相等的格子,每个格子称为数组的元素int代表每个元素的类型,可以是任意基本类型,也可以是组合类型,甚至可以是数组初......
  • 嵌入式基础 C语言篇 指针初阶
    一、指针的入门(1)、预备知识0、图解:1、内存地址字节:字节是内存的容量单位,英文称为byte,一个字节有8位,即1byte(00000000---11111111)=8bits(0---1)地址:系统为了便于区分每一个字节而对它们逐一进行的编号,称为内存地址,简称地址。在32位系统:说明:地址+1就是......
  • 嵌入式基础 C语言篇 错题
    (1) 若已定义x和y为double类型,则表达式x=1,y=x+3/2的值是________。A.1     B.2    C.2.0    D.2.53/2=1;y=2.0(2)简述i++和++i    i++是先使用i的值,再i+1;++i是先i+1,再使用i的值底层原理:1、i++和++i都是带有返回值的函数2......
  • base中TCP/IP基础学习笔记
    base中的网络模型的学习笔记一.关于TCP/IP网络模型引言对于同一台设备上的进程间通信,有很多种方式,有管道、消息队列、共享内存、信号等方式,对于不同设备上的进程间通信,就需要网络通信,设备是多样的,所以要兼容各种各样的设备,就协商出了一套通用的网络协议。网络协议是分层......
  • C++基础学习03
    C++基础学习032025-01-1715:59:09星期五关于数组数组有几个特点固定大小相同的数据类型连续存储这点就是说数组在内存中是连续存储的下标访问这点就是我们可以通过[num]的方式来对数组进行访问一般来说,我们使用dataTypearrayName[arraySize]的方式来创建......
  • Java基础
    注释种类单行注释//内容多行注释/*内容*/文档注释/**内容*/写注释是很好的习惯!!!标识符注意点以字母/美元/_为开头标识符是大小写敏感的,所以一定要注意类名no中文,标识符no拼音数据类型强类型语言:变量的使用要严格符合规定,所有变量必须先定义才能使用......
  • 单片机系统思想基础①
     一、面向MCU1、采样类(物理接口)  模拟采样(ADC采样)、   数字采样(边沿采样、电平采样)2、控制类(物理接口)  PWM控制   DAC控制类   数字输出控制(GPIO输出控制))3、通信类(物理接口)  串口通信   SPI通信   IIC通信   USB通......
  • 基础知识
    环境部署计算机组成硬件主要组成部分:中央处理器(CPU)、内存(RAM)、存储设备(硬盘)、主板、显卡(GPU)、电源、输入输出设备软件系统软件:Windows、Linux、IOS、Android等等应用软件:微信、QQ、office办公软件JDK-JRE-JVM组件全称描述JDKJava开发工具包(JavaDevelo......
  • 测试 | 车载智能座舱基础知识
    1.VAD(voiceactivitydetection)语音活动检测也称为静音检测,是用来判断用户是否已经说完话,然后通过结果判断是否进行回答。开始语音识别之前,把首尾端的静音切除,以防对后续步骤进行干扰。如果此时用户还没有说完话,就停止识别了开始回答,会造成理解不当,回答不精准的情况;但是如果......
  • 2025.1.18 JavaScript基础
    1、变量的定义var变量名例如:<html> <body> <scripttype="text/javascript"> functionzhaoling(){ n=Number(document.form1.txt1.value); if(n!=parseInt(n/1)||n<1||n>100) { alert("请输入一个1-100的整数"); ......