一、树の存储结构
1.树の三种表示法
双亲表示法(顺序存储):更像是单亲。
孩子表示法(顺序+链式存储):用一个顺序空间(数组)存储各个结点的数据。
2.树、二叉树、森林の转换
树转二叉树:对每个结点,左孩子还是左孩子,把兄弟结点变成右孩子。
二叉树转树:左孩子还是孩子,右孩子变右兄弟。
森林转二叉树(用二叉链表存储森林):
把互不相见的树依次转化成二叉树,把它们的根节点看成兄弟结点,用右指针连起来。
二叉树转森林(孩子兄弟表示法存储森林):对每个结点来说,左边连的是自己的孩子,右边连的是兄弟(自己父节点的下一个孩子)
二、遍历
总览:
树的先根遍历序列与其对应的二叉树的先序遍历序列相同。
根结点的右孩子变成了左孩子的右孩子。
树的后跟遍历序列和其对应的二叉树的中序遍历序列相同。
这是因为在将树转化为二叉树的过程中,每个节点的右子树都是空的。因此,在进行后根遍历时,会首先遍历所有的子树,然后再访问根节点。这就意味着在二叉树中,我们会首先访问所有的左子节点(也就是原始树中的子树),然后再访问根节点。这正是二叉树中序遍历的定义。
左孩子->右孩子->根——>左孩子->左孩子的兄弟->根==二叉树的中序遍历
左孩子->根->右孩子——>左孩子->根->左孩子的爹的兄弟==树的后根遍历
所以,一棵树的后根遍历序列等于它对应的二叉树的中序遍历序列。这种关系在将森林转化为二叉树时也同样适用。具体来说,森林的第一棵树的子树森林会转换成左子树,剩余的树构成的森林会转换成右子树。因此,森林的先序和中序遍历对应于二叉树的先序和中序遍历。
树的层次(广度优先)遍历:用一个辅助队列实现,让根节点入队,让根节点出队,如果有子结点,所有子结点依次入队,重复该过程。
森林的先序遍历:
方法1:效果等同于依次对各个子树先根遍历
考试手算时,很不推荐钻到两层递归嵌套里,直接对各个子树进行先根遍历即可。
方法2:转化成二叉树再先序遍历。
森林的中序遍历:
方法1:对各个子树进行后跟遍历。
方法2:转化成二叉树进行中序遍历
值得注意的是,森林的中序遍历与二叉树的中序遍历方法的定义不同。在二叉树的中序遍历中,我们按照左-根-右的顺序进行遍历。而在森林的中序遍历中,我们首先中序遍历第一棵树的所有子树,然后访问这棵树的根节点(可以理解为:对于森林来说,根据左孩子右兄弟原则,中序遍历的左-根-右其实就是左孩子-根-右兄弟)。对于这棵树来说,根节点的访问次序其实是整棵树遍历的最后(类似于二叉树的后序),这里经常与二叉树的中序遍历混淆。
此外,有些人可能会对为什么称之为“中序”遍历感到困惑。实际上,这是因为这种遍历等同于将森林转换为二叉树之后,对二叉树进行的中序遍历。因此,尽管在处理每个单独的树时,它更像是后序遍历,但由于它等同于整个森林转换为二叉树后的中序遍历,所以被称为“中序”遍历。