最全数据结构与算法——树与二叉树_数据结构与算法树和二叉树,2024年最新面试复盘

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

结点的层次(Level) 是从根开始定义的,根为第一层,根的孩子为第二层✍(自上往下数)
📌以上图为例,结点G的层次为3

树中结点的最大层次称为树的深度(Depth) 或高度✍(其实就是整棵树总共有多少层)
📌以上图为例,树的深度或高度为4

👉结点数 = 总度数 + 1👈
📌以上图为例,结点A的度数为3;结点B的度数为2;结点C的度数为1,结点D的度数为3;结点E的度数为2;结点H的度数为1;其余结点K、L、F、G、M、I、J的度数为0,所以这棵树的结点数就等于:

📌T结点数 = 3+2+1+3+2+1+1;最后结果为13

🚢有序树和无序树

有序树——逻辑上看,树中结点的各子树从左至右是有次序的,不能互换

无序树——逻辑上看,树中结点的各子树从左至右是无次序的,可以互换

🚢森林

👉森林(Forest)👈

m

m

=

0

m(m>=0)

m(m>=0)棵互不相交的树的集合,对树中的每个结点而言,其子树的集合即为森林。

📌森林可以为空

在这里插入图片描述


🚀二叉树

🚢二叉树的定义

👉二叉树(Binary Tree)👈是另一种树型结构,它的特点是每个结点至多只有两棵子树(✍即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒

在这里插入图片描述

二叉树或为空,或是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树构成,由于这两棵子树也是二叉树,则由二叉树的定义,它们也可以是空树。由此,二叉树可以有5中基本形态

在这里插入图片描述

🚢二叉树的性质

二叉树具有下列重要特性

🚗性质一: 在二叉树的第

i

i

i 层上之多有 2i-1 个结点(

i

=

1

i>=1

i>=1)

🚗性质二: 深度为

k

k

k 的二叉树之多有 2k-1 个结点(

k

=

1

k>=1

k>=1)

🚗性质三: 对任何一棵二叉树T,如果其终端结点数为

n

0

n0

n0,度为2的结点数为

n

2

n2

n2,则有

n

0

=

n

2

1

n0=n2+1

n0=n2+1

在这里插入图片描述

🚢满二叉树

一棵深度为

k

k

k 且有 2k-1 个结点的二叉树称为👉满二叉树👈,这种树的✍特点是每一层上的结点数都是最大结点数,只有最后一层是叶子结点且不存在度为1的结点

在这里插入图片描述

🚢完全二叉树

深度为

k

k

k 的,有

n

n

n 个结点的二叉树,当且仅当其每一个结点都与深度为

k

k

k 的满二叉树中编号从1至

n

n

n 的结点一一对应时,称之为👉完全二叉树👈✍在一棵完全二叉树中只有最后两层可能为叶子结点,且最多只有一个度为1的结点。

在这里插入图片描述

✨完全二叉树的两个重要特性:

🚗特性一: 具有

n

n

n个结点的完全二叉树的深度为

l

o

g

2

n

log2n

log2n向下取整+1

🚗特性二: 如果对一棵有

n

n

n个结点的完全二叉树(其深度为

l

o

g

2

n

log2n

log2n向下取整+1)的结点按层序编号(从第一层到第

l

o

g

2

n

log2n

log2n向下取整+1层,每层从左到右),则对任一结点

i

1

<

=

i

<

=

n

i(1<=i<=n)

i(1<=i<=n),有以下结论:

如果

i

=

1

i=1

i=1,则结点

i

i

i是二叉树的根,无双亲,如果

i

1

i>1

i>1,则双亲(Parent)为结点

i

/

2

i/2

i/2向下取整;

如果

2

i

n

2i>n

2i>n,则结点i无左孩子(结点

i

i

i为叶子结点);否则其左孩子(Lchild)是结点2i;

如果

2

i

1

n

2i+1>n

2i+1>n,则结点i无右孩子,否则其右孩子(Rchild)是结点

2

i

1

2i+1

2i+1;

在这里插入图片描述

🚗特性三: 满二叉树是一种特殊的完全二叉树,但完全二叉树不一定是满二叉树

🚢二叉排序树

左子树上所有结点的关键字均小于根结点的关键字,右子树上所有结点的关键字均大于根结点的关键字,左子树和右子树又各是一棵二叉排序树。

✨二叉排序树用于元素的搜索和排序。
在这里插入图片描述

🚢平衡二叉树

树上任何一个结点的左子树和右子树的深度之差不超过1。

✨平衡二叉树能有更高的搜索效率。

在这里插入图片描述

🚢二叉树的存储结构
🌈顺序存储结构

按照顺序存储结构的定义,用一组地址连续的存储单元依次✍自上而下、从左往右存储完全二叉树的结点元素,即将完全二叉树上编号为

i

i

i的结点元素存储在如上定义的一维数组中下标为

i

1

i-1

i−1的分量中。

//二叉树的顺序存储表示
#define MaxSize 100 //二叉树的最大结点数
struct TreeNode
{
   ElemType value;      //结点中的数据元素
   bool isEmpty;        //结点是否为空
};

//定义一个长度为MaxSize的数组t,按照从上而下,从左至右的顺序依次存储二叉树中的各个结点
TreeNode t[MaxSize];


对于一般二叉树,则应将其每个结点与完全二叉树上的结点相对照,存储在一维数组中的对应分量中。✍顺序存储结构更多仅适用于完全二叉树的存储。

🌈链式存储结构

由二叉树的定义得知,二叉树的结点由一个数据元素和分别指向其左、右子树的两个分支构成,则表示二叉树的链表中的结点至少包含三个域:👉数据域👈👉左、右指针域👈。有时,为了便于找到结点的双亲,则还可以在结点结构中增加一个指向其双亲结点的指针域。 利用这两种结点结构所得的二叉树的存储结构分别称之为👉二叉链表👈👉三叉链表👈。

//二叉树的二叉链表存储表示
typedef struct BiTNode
{
    TElemType data;		//数据域
    struct BiTNode \*lchild, \*rchild      //左右孩子指针
}BiTNode,\*BiTree;


🚢二叉树的遍历

在二叉树的一些应用中,常常要求在树中查找具有某种特征的结点,或者对树中全部结点逐一进行某种处理。回顾二叉树的递归定义可知,二叉树是由三个基本单元组成:根节点、左子树和右子树,因此,✍二叉树的遍历分为先(根)序遍历、中(根)序遍历、后(根)序遍历和层次遍历。

🚩先(根)序遍历二叉树的操作定义为(根左右):
若二叉树为空,则空操作,否则:

  • 访问根结点;
  • 先序遍历左子树;
  • 先序遍历右子树;
    在这里插入图片描述

🚩中(根)序遍历二叉树的操作定义为(左根右):
若二叉树为空,则空操作,否则:

  • 中序遍历左子树;
  • 访问根结点;
  • 中序遍历右子树;
    在这里插入图片描述

🚩后(根)序遍历二叉树的操作定义为(左右根):
若二叉树为空,则空操作,否则:

  • 后序遍历左子树;
  • 后序遍历右子树;
  • 访问根结点;
    在这里插入图片描述

🚩层次遍历二叉树的操作定义为:

  • 初始化一个队列;
  • 根结点入队;
  • 若队列非空,则队头结点出队,访问该结点,并将其左、右孩子插入队尾;
  • 重复上一步,直到队列为空
    在这里插入图片描述
🚢线索二叉树

在遍历二叉树时,要想找到某个结点的前驱和后继的信息,得运用二叉树已知的遍历方法从头开始遍历,然后在遍历的过程中动态获取其结点的前驱和后继的信息,那有没有一种方法是已知该结点就已经知道其前驱和后继的信息了呢?答案肯定是有的,为了解决二叉树遍历时所存在的一些问题,线索二叉树也孕育而生。那什么是👉线索二叉树👈呢?

简单理解就是✍利用空链域来存放结点的前驱和后继的信息,方便寻找前驱结点和后继结点,提高遍历效率。因为n个结点的二叉树,有

n

1

n+1

n+1个空链域,所以可以利用这些空链域来记录前驱,后继的信息。**若结点有左子树,则其

l

c

h

i

l

d

lchild

lchild域指示其左孩子,否则令

l

c

h

i

l

d

lchild

lchild域指示其前驱;若结点有右子树,则其

r

c

h

i

l

d

rchild

rchild域指示其右孩子,否则令

r

c

h

i

l

d

rchild

rchild域指示其后继。为了避免混淆,尚需改变结点结构,增加两个标志域**
在这里插入图片描述

以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做👉线索链表👈。其中指向结点前驱和后继的指针,叫做👉线索👈。加上线索的二叉树又称之为👉线索二叉树(Threaded Binary Tree)👈。对二叉树以某种次序遍历使其变为线索二叉树的过程叫做👉线索化👈

📌在线索树上进行遍历,只要先找到序列中的第一个结点,然后依次找结点后继直至其后继为空时而止。


🚀树和森林

🚢树的存储结构

双亲表示法

每个结点中保存指向 “双亲” 的指针。

优点:查找指定结点的双亲很方便

缺点:查找指定结点的孩子只能从头遍历

//树的双亲表示法存储表示
#define MAX\_TREE\_SIZE 100
typedef struct PTNode{      //结点结构
    TElemType data;
    int parent;     //双亲位置域
}PTNode;
typedef struct{     //树结构
    PTNode nodes[MAX_TREE_SIZE];
    int r,n;    //根的位置和结点数
}PTree;

孩子表示法(顺序+链式存储)

//树的孩子表示法链表存储表示
typedef struct CTNode{      //孩子结点
    int child;
    struct CTNode \*next;
}\*ChildPtr;
typedef struct{
    TElemType data;
    ChildPtr firstchild;    //孩子链表头指针
}CTBox;
typedef struct{
    CTBox nodes[MAX_TREE_SIZE];
    int n,r;        //结点数和根的位置
}CTree;

子兄弟表示法(链式存储)

优点,可以利用二叉树操作来处理树

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

双亲表示法

每个结点中保存指向 “双亲” 的指针。

优点:查找指定结点的双亲很方便

缺点:查找指定结点的孩子只能从头遍历

//树的双亲表示法存储表示
#define MAX\_TREE\_SIZE 100
typedef struct PTNode{      //结点结构
    TElemType data;
    int parent;     //双亲位置域
}PTNode;
typedef struct{     //树结构
    PTNode nodes[MAX_TREE_SIZE];
    int r,n;    //根的位置和结点数
}PTree;

孩子表示法(顺序+链式存储)

//树的孩子表示法链表存储表示
typedef struct CTNode{      //孩子结点
    int child;
    struct CTNode \*next;
}\*ChildPtr;
typedef struct{
    TElemType data;
    ChildPtr firstchild;    //孩子链表头指针
}CTBox;
typedef struct{
    CTBox nodes[MAX_TREE_SIZE];
    int n,r;        //结点数和根的位置
}CTree;

子兄弟表示法(链式存储)

优点,可以利用二叉树操作来处理树

[外链图片转存中…(img-3Mzyq0fr-1715806427922)]
[外链图片转存中…(img-kWEnv6bz-1715806427923)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值