This commit is contained in:
chefyuan 2021-05-06 13:35:29 +08:00
parent b47322ceb3
commit a0cc85f6ee

View File

@ -82,7 +82,7 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
我们刷题时遇到的就是二叉树啦下面我们一起来了解一下二叉树
二叉树前提是一棵树也就是**需要满足我们树的定义的同时**还需要满足以下要求
二叉树前提是一棵树也就是`需要满足我们树的定义的同时`还需要满足以下要求
每个节点`最多`有两个子节点分别是左子节点和右子节点
@ -91,7 +91,7 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
下面我们来总结一下二叉树的特点
- 每个节点最多有两棵子树也就是说二叉树中不存在度大于 2 的节点节点的度可以为 012
- 左子树和右子树是有顺序的
- 左子树和右子树是有顺序的,有左右之分
- 假如只有一棵子树 也要区分它是左子树还是右子树
好啦我们已经了解了二叉树的特点那我们分析一下下图中的树是否满足二叉树定义共有几种二叉树
@ -100,11 +100,11 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
上图共为 5 种不同的二叉树在二叉树的定义中二叉树的左子树和右子树是有顺序的所以上图为 5 种不同的二叉树
上图共为 5 种不同的二叉树在二叉树的定义中提到二叉树的左子树和右子树是有顺序的所以 BC 是两个不同的二叉树上图为 5 种不同的二叉树
## 特殊的二叉树
下面我们来说几种比较特殊的二叉树可以帮助我们刷题时考虑到特殊情况
下面我们来说几种比较特殊的二叉树可以`帮助我们刷题时考虑到特殊情况`
### 满二叉树
@ -112,7 +112,7 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
![](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/image.2k1tlbtywzu0.png)
我们发现只有 (B) 符合满二叉树的定义,我们发现其实满二叉树也为完全二叉树的一种
我们发现只有 (B) 符合满二叉树的定义,我们发现其实满二叉树也为完全二叉树的一种
### 完全二叉树
@ -134,7 +134,9 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
![](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/image.6u1n2j3jmu80.png)
另外还有 一些二叉树的性质, 比如第 i 层至多有多少节点,通过叶子节点求度为 2 的节点, 通过节点树求二叉树的深度等, 这些是考研常考的知识,刷题时一般不太用到, 所以不在这里赘述,需要的同学可以看一下王道或者天勤的数据结构, 上面描述的很具体, 并附有证明过程.
另外还有 一些二叉树的性质, 比如第 i 层至多有多少节点,通过叶子节点求度为 2 的节点, 通过节点树求二叉树的深度等, 这些是考研常考的知识, 就不在这里进行赘述,需要的同学可以看一下王道或者天勤的数据结构, 上面描述的很具体, 并附有证明过程.
好啦我们已经了解了二叉树那么二叉树如何存储呢
## 如何存储二叉树
@ -144,7 +146,7 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
**一个破堆排我搞了 4 个动画?**
这里我们再来一下如何用数组存储完全二叉树.
这里我们再来回顾一下如何用数组存储完全二叉树.
![](https://cdn.jsdelivr.net/gh/tan45du/test@master/photo/微信截图_20210223223621.3juf4t4hc9a0.png)
@ -152,15 +154,15 @@ PS本篇文章内容较基础对于没有学过数据结构的同学会有
我们发现其中的关系了吗
数组中某节点非叶子节点的下标为 i , 那么其**左子节点下标为 2*i** 这里可以直接通过相乘得到左孩子, 也就是为什么空出第一个位置, 如果从 0 开始存则需要 2*i+1 才行, 右子节点为 2*i+1其父节点为 i/2 既然我们完全可以根据索引找到某节点的 **左子节点** **右子节点**那么我们用数组存储是完全没有问题的
数组中某节点非叶子节点的下标为 i , 那么其`左子节点下标为 2*i `这里可以直接通过相乘得到左孩子, 也就是为什么空出第一个位置, 如果从 0 开始存则需要 2*i+1 才行, 右子节点为 2*i+1其父节点为 i/2 既然我们完全可以根据索引找到某节点的 `左子节点` ` 右子节点`那么我们用数组存储是完全没有问题的
但是,我们再考虑一下这种情景,如果我们用数组存储`斜树`时会出现什么情况?
![](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/image.6ox0r00g6e40.png)
![](https://cdn.jsdelivr.net/gh/tan45du/test@master/image.780as9g3ofs0.png)
通过 2*i 进行存储左子节点的话,如果遇到斜树时,则会浪费一半的存储空间,这样显然是不合适的,
通过 2*i 进行存储左子节点的话,如果遇到斜树时,则会浪费很多的存储空间,这样显然是不合适的,
所以说当存储完全二叉树时,我们用数组存储,无疑是最省内存的
所以说当存储完全二叉树时,我们用数组存储,无疑是最省内存的但是存储斜树时则就不太合适
所以我们下面介绍一下另一种存储结构,链式存储结构.
@ -191,21 +193,21 @@ public class BinaryTree {
}
```
另外我们在刷题的时候, 可以自己实现一下数据结构, 加深我们的理解, 提升基本功, 而且面试考的也越来越多.
另外我们在刷题的时候, 可以`自己实现一下数据结构`, 加深我们的理解, 提升基本功, 而且面试考的也越来越多.
好啦,下面我们说一下树的遍历,
下面我会用动图的形式进行描述,很容易理解, 我也会为大家总结对应的题目, 题目对应的代码我会放到我的仓库,欢迎各位阅读.
下面我会用动图的形式进行描述,很容易理解, 我也会为大家总结对应的题目,欢迎各位阅读.
## 遍历二叉树
二叉树的遍历指**从根节点出发**,**按照某种次序依次访问二叉树的所有节点**,使得每个节点都被访问且访问一次.
二叉树的遍历指`从根节点出发,按照某种次序依次访问二叉树的所有节点`,使得每个节点都被访问且访问一次.
我们下面介绍二叉树的几种遍历方法及其对应的题目, 前序遍历, 中序遍历 , 后序遍历 , 层序遍历 .
### 前序遍历
前序遍历的顺序是, 对于树中的某节点,先遍历该节点,然后再遍历其左子树,最后遍历其右子树.
前序遍历的顺序是, 对于树中的某节点,`先遍历该节点,然后再遍历其左子树,最后遍历其右子树`.
只看文字有点生硬, 下面我们直接看动画吧
@ -240,11 +242,11 @@ class Solution {
时间复杂度 : O(n) 空间复杂度 : O(n) 为递归过程中栈的开销,平均为 O(logn),但是当二叉树为斜树时则为 O(n)
为了控制文章篇幅, 二叉树的迭代遍历形式, 会在下篇文章进行介绍
为了控制文章篇幅, 二叉树的迭代遍历形式, 会在下篇文章进行介绍
### 中序遍历
中序遍历的顺序是, 对于树中的某节点,先遍历该节点的左子树, 然后再遍历该节点, 最后遍历其右子树
中序遍历的顺序是, `对于树中的某节点,先遍历该节点的左子树, 然后再遍历该节点, 最后遍历其右子树`
继续看动画吧, 如果有些遗忘或者刚开始学数据结构的同学可以自己模拟一下执行步骤.
@ -281,7 +283,7 @@ class Solution {
### 后序遍历
后序遍历的顺序是, 对于树中的某节点, 先遍历该节点的左子树, 再遍历其右子树, 最后遍历该节点.
后序遍历的顺序是,` 对于树中的某节点, 先遍历该节点的左子树, 再遍历其右子树, 最后遍历该节点`.
哈哈,继续看动画吧,看完动画就懂啦.
@ -322,15 +324,15 @@ class Solution {
二叉树的层序, 这里我们需要借助其他数据结构来实现, 我们思考一下, 我们需要对二叉树进行层次遍历, 从上往下进行遍历, 我们可以借助什么数据结构来帮我们呢 ?
我们可以使用队列, 具体操作如下
我们可以利用队列先进先出的特性使用队列来帮助我们完成层序遍历, 具体操作如下
让二叉树的每一层入队, 然后再依次执行出队操作,
该层节点执行出队操作时, 需要将该节点的左孩子节点和右孩子节点进行入队操作,
`该层节点执行出队操作时, 需要将该节点的左孩子节点和右孩子节点进行入队操作`,
这样当该层的所有节点出队结束后, 下一层也就入队完毕,
不过我们需要考虑的就是, 我们需要通过一个变量来保存每一层节点的数量.
不过我们需要考虑的就是, 我们`需要通过一个变量来保存每一层节点的数量`.
这样做是为了防止, 一直执行出队操作, 使输出不能分层