资海网络一年做多少网站,优必选网站,在贸易网站怎么做贸易,wordpress linux 安装关卡名 理解树的特征 我会了✔️ 内容 1.理解树的结构、基本概念、性质以及存储方式 ✔️ 2.理解树的前中后三种遍历方式 ✔️ 3.理解如何使用前中序列和中后序列来构造树 ✔️
1 树的常见概念
树是一个有n个有限节点组成一个具有层次关系的集合#xff0c;每个节点有0… 关卡名 理解树的特征 我会了✔️ 内容 1.理解树的结构、基本概念、性质以及存储方式 ✔️ 2.理解树的前中后三种遍历方式 ✔️ 3.理解如何使用前中序列和中后序列来构造树 ✔️
1 树的常见概念
树是一个有n个有限节点组成一个具有层次关系的集合每个节点有0个或者多个子节点没有父节点的节点称为根节点也就是说除了根节点以外每个节点都有父节点并且有且只有一个。树的种类比较多我们最常见的应该是二叉树了基本结构如下 参考上面的结构可以很方便的理解树的如下概念
节点的度:一个节点含有的子节点的个数称为该节点的度;树的度:一棵树中最大的节点的度称为树的度注意与节点度的区别叶节点或终端节点:度为0的节点称为叶节点;非终端节点或分支节点:度不为0的节点;双亲节点或父节点:若一个节点含有子节点则这个节点称为其子节点的父节点;孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;兄弟节点:具有相同父节点的节点互称为兄弟节点;节点的祖先:从根到该节点所经分支上的所有节点;子孙:以某节点为根的子树中任一节点都称为该节点的子孙。森林:由m(m0)棵互不相交的树的集合称为森林;无序树:树中任意节点的子节点之间没有顺序关系这种树称为无序树也称为自由树;有序树:树中任意节点的子节点之间有顺序关系这种树称为有序树;二叉树:每个节点最多含有两个子树的树称为二叉树;
2 树的性质
性质1: 在二叉树的第i层上至多有2^(i-1)个结点i0性质2: 深度为k的二叉树至多有2^k - 1个结点k0性质3: 对于任意一棵二叉树如果其叶结点数为N0而度数为2的结点总数为N2则N0N21;性质4:具有n个结点的完全二叉树的深度必为 log2(n1)性质5:对完全二叉树若从上至下、从左至右编号则编号为i 的结点其左孩子编号必为2i 其右孩子编号必为2i1其双亲的编号必为i/2i1 时为根,除外 满二叉树和完全二叉树是经常晕的问题我们有必要单独看一下。满二叉树就是如果一棵二叉树只有度为0的节点和度为2的节点并且度为0的节点在同一层上则这棵二叉树为满二叉树。 这棵二叉树为满二叉树也可以说深度为k4有2^k-115个节点的二叉树。 完全二叉树的定义如下:在完全二叉树中除了最底层节点可能没填满外其余每层节点数都达到最大 值并且最下面一层的节点都集中在该层最左边的若干位置。 这个定义最邪乎了估计大部分看了之后还是不懂什么是完全二叉树看这个图就知道了 前面两棵树的前n-1层都是满的最后一层所有节点都集中在左侧区域而且节点之间不能有空隙。最后一个为什么不是因为有一节点缺了一个左子节点。
3 树的定义与存储方式
注意本关讲义我们主要看原理不写可执行的代码因此我们只用伪码不提供各种语言的定义
定义树的原理与前面讲的链表本质上是一样的只不过多了一个指针如果是二叉树只要在链表的定义上增加一个指针就可以了
定义二叉树 public class TreeNode { int val; TreeNode left; TreeNode right; } 这里本质上就是有两个引用分别指向两个位置为了便于理解我们分别命名为左孩子和右孩子。如果是N叉树该如何定义呢其实就是每个节点最多可以有N个指针指向其他地方这是不用left和right使用一个List就可以了也就是
定义N叉树 public class TreeNode { int val; ListTreeNode nodes; } 那能否用数组来存储二叉树呢?其实就是用数组来存储二叉树顺序存储的方式如图: 用数组来存储二叉树如何遍历的呢?如果父节点的数组下表是i那么它的左孩子就是i * 2 1右孩子就是 i * 2 2。但是用链式表示的二叉树更有利于我们理解所以一般我们都是用链式存储二叉树。所以大家要了解用数组依然可以表示二叉树。 使用数组存储的最大不足是可能存在大量的空间浪费。例如上图中如果b分支没有那么数组种1 3 4 位置都要空着但是整个数组的大小仍然是7因此很少使用数组来存储树。
4 树的遍历方式
我们现在就来看一下树的常见遍历方法。二叉树的遍历方式有层次遍历和深度优先遍历两种:
深度优先遍历:先往深走遇到叶子节点再往回走。广度优先遍历:一层一层的去遍历一层访问完再访问下一层。
这两种遍历方式不仅仅是二叉树N叉树也有这两种方式的图结构也有只不过我们更习惯叫广度优先和深度优先本质是一回事。深度优先又有前中后序三种 有同学总分不清这三个顺序问题就在不清楚这里前中后是相对谁来说的。记住一点前指的是中间的父节点在遍历中的顺序只要大家记住 前中后序指的就是中间节点的位置就可以了。 看如下中间节点的顺序就可以发现访问中间节点的顺序就是所谓的遍历方式 前序遍历:中左右 中序遍历:左中右 后序遍历:左右中 大家可以对着如下图看看自己理解的前后中序有没有问题。 后面大量的算法都与这四种遍历方式有关有的题目根据处理角度不同 可以用层次遍历也可以用一种甚至两种深度优先的方式来实现。
5 通过序列构造二叉树
前面我们已经介绍了前中后序遍历的基本过程现在我们看一下如何通过给出的序列来恢复原始二叉树看三个序列 (1) 前序1 2 3 4 5 6 8 7 9 10 11 12 13 15 14 (2) 中序3 4 8 6 7 5 2 1 10 9 11 15 13 14 12 (3) 后序8 7 6 5 4 3 2 10 15 14 13 12 11 9 1
5.1 前中序列复原二叉树
我们先看如何通过前中序列复原二叉树 (1) 前序1 2 3 4 5 6 8 7 9 10 11 12 13 15 14 (2) 中序3 4 8 6 7 5 2 1 10 9 11 15 13 14 12
第一轮
我们知道前序第一个访问的就是根节点所以根节点就是1。 中序遍历的特点是根节点的左子树的元素都在根节点的左侧右子树的元素都在根节点的右侧从中序遍历序列我们可以划分成如下结构 中序序列划分 [3 4 8 6 7 5 2] 1[ 10 9 11 15 13 14 12] 前序序列划分为 1 [2 3 4 5 6 8 7 ] [9 10 11 12 13 15 14] 上面前序序列第一个括号里的都是左子树的元素第二个括号一定都是右子树的元素。 那这里怎么知道两个括号从哪里分开呢是参照中序的两个数组划分的。我们看到前序中7之前的元素都在中序第一个数组中9之后的所有元素就在第二个数组种所以我们从7和9之间划分。 由此画图表示一下此时知道的树的结构为 第二轮
我们先看两个序列的第一个数组 前序2 3 4 5 6 8 7 中序3 4 8 6 7 5 2 此时又可以利用上面的结论划分了根节点是2然后根据2在中序中的位置可以划分为 前序2 [3 4 5 6 8 7 ] 中序[3 4 8 6 7 5 ] 2 所以此时的树结构为 第三轮
对 3 4 5 6 8 7 继续划分前序3 [4 5 6 8 7 ] 中序3 [4 8 6 7 5 ]此时结构为 第四轮 :
对 4 5 6 8 7 继续划分前序4 [5 6 8 7 ] 中序4 [8 6 7 5 ] 此时树为
第五轮对 5 6 8 7 继续划分前序5 [6 8 7 ] 中序[8 6 7 ] 5
这个题有点恶心每次只能确定一个元素道理是这样子直接画最终结果吧 这个图有点丑我们将空节点都去掉就是这样了 同理对于序列[ 10 9 11 15 13 14 12]我们也可以逐步划分这个请读同学自己试一试最终结果为 5.2 通过中序和后序序列恢复二叉树
通过中序和后序也能恢复原始序列的唯一的不同是后序序列的最后一个是根节点中序的处理也是上面一样的过程
前序1 2 3 4 5 6 8 7 9 10 11 12 13 15 14中序3 4 8 6 7 5 2 1 10 9 11 15 13 14 12后序8 7 6 5 4 3 2 10 15 14 13 12 11 9 1
读者可以自行试一试我们就不再赘述。问题为什么前序和后序不能恢复二叉树 既然上面两种都行那为什么前序和后序不行呢我们看上面的例子
(1) 前序1 2 3 4 5 6 8 7 9 10 11 12 13 15 14 (2) 后序8 7 6 5 4 3 2 10 15 14 13 12 11 9 1 根据上面的说明我们通过前序可以知道根节点是1通过后序也能知道根节点是1但是中间是怎么划分的呢其他元素哪些属于左子树哪些属于右子树呢很明显通过两个序列都不知道所以前序和后序序列不能恢复二叉树。 如果将上述过程用代码实现该怎么做呢通过前序和中序构造树就是LeetCode105题通过中序和后序构造树就是LeetCode106题实现过程略微繁琐感兴趣的同学可以研究一下。