二叉树的构造与算法
同一棵二叉树(节点值均不相同)具有唯一的先序、中序、后序序列和层次序列,但不同的二叉树可能具有相同的先序、中序序列、后序序列和层次序列,二叉树的构造就是根据提供的某些遍历序列构造二叉树的结构。
由先序序列和中序序列构造二叉树:先序序列提供了二叉树的根节点的信息(任何一棵二叉树的先序序列的第一个节点为根节点),而中序序列提供了由根节点将整个序列分为左、右子树的信息。
- 确定树的根节点:先序遍历的第一个节点
- 求解树的子树:找出根节点在中序遍历中的位置,根左边的是左子树,右边的是右子树。
- 递归求解树:将左子树和右子树看成一棵二叉树,重复上面步骤  
由后序序列和中序序列构造二叉树:后序序列提供了二叉树的根节点的信息(任何一棵二叉树的后序序列的最后一个节点为根节点),而中序序列提供了由根节点将整个序列分为左、右子树的信息。
- 确定树的根节点:后序遍历的最后一个节点
- 求解树的子树:找出根节点在中序遍历中的位置,根左边的是左子树,右边的是右子树。
- 递归求解树:将左子树和右子树看成一棵二叉树,重复上面步骤  
由层次序列和中序序列构造二叉树:层次序列提供了二叉树的根节点的信息(任何一棵二叉树的层次序列的第一个节点为根节点),而中序序列提供了由根节点将整个序列分为左、右子树的信息。
- 确定树的根节点:层次遍历的第一个节点
- 求解树的子树:找出根节点在中序遍历中的位置,根左边的是左子树,右边的是右子树。
- 递归求解树:将左子树和右子树看成一棵二叉树,重复上面步骤。 
森林和二叉树的相互转换
- 树转换为二叉树 
- 森林转换为二叉树 
二叉树转换为树
二叉树转换为森林


树的先序遍历与其转换的相应的二叉树的先序遍历的结果序列相同
树的后序遍历与其转换的二叉树的中序遍历的结果序列相同
森林的先序遍历和中序遍历与所转换得到的二叉树的先序遍历和中序遍历的结果序列相同。
假设一棵二叉树采用二叉链存储结构,设计一个算法求二叉树的高度。
- 方式 \(1\) —采用递归方式「基于后序遍历」,先计算左子树的高度,然后计算右子树的高度,最后比较左、右子树的高度,返回较大的那个高度\(+1\)就是二叉树的高度。  
- 方式 \(2\) —采用层次遍历,基本思路是访问完每一层的所有节点之后则二叉树的深度加 \(1\)。若根节点为空,则返回 \(0\),若根节点为非空,则第一层的节点个数肯定为 \(1\)个,当第一个节点出栈后二叉树的深度就加 \(1\)了,然后记录这个节点的子节点的个数,当第二层的所有节点都出完队后,也就是第二层的节点都访问完了,此时二叉树的深度加\(1\),如此重复,直到遍历完二叉树。   采用一个变量\(last\)记录每层的最右节点,当访问节点的 \(front==last\) 时,即表示这一层访问结束,这时高度应该加\(1\)。 
- 方式 \(3\)—采用二叉树的后序遍历非递归算法。根据二叉树后序遍历的定义,先访问根结点的左子节点,然后访问根结点的右子节点,最后访问根结点。如果节点值非空,首先应该进入该节点的左子树访问,此时由于该节点的右子树及根结点尚未访问,因此必须将该节点保存起来,放入栈中,以便访问完左子树后,从栈中取出该节点,进行其右子树及根结点的访问。确切的说,当一个元素位于栈顶即将处理时,其左子树的访问一定已经完成,如果其右子树尚未遍历,接下来应该进入其右子树访问,而此时该栈顶元素是不能出栈的,因为其根结点还未被访问;只有等到其右子树也访问完成后,该栈顶元素才能出栈。所以,后序遍历能够找出最长的路径,每次节点进栈后,求出当前栈的大小,遍历结束后返回最大的栈长度即为树的深度。 
假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树\(b\)的宽度(即具有节点数最多的那一层的节点个数)。
- 方式 \(1\),采用层次遍历:在遍历的时候记录每个节点的所在的层次,然后求层次值最大的平台。  
- 方式 \(2\): 采用层次遍历:直接记录每一层的节点数目,然后将每一层的节点数目和当前最大的那个比较,得出最终的宽度。  
假设一棵二叉树采用二叉链存储结构,设计一个算法求二叉树中的所有叶子节点。

假设二叉树采用二叉链表存储结构,设计一个算法把二叉树 \(b\) 复制到 \(t\) 中。

假设二叉树采用二叉链表存储结构,设计一个算法将二叉树的左右子树进行交换,要求不破坏原二叉树。

假设二叉树采用二叉链表存储结构,设计一个算法判断两棵二叉树是否相等。

设计一个算法将二叉树的顺序存储结构转换为二叉链表存储。

设计一个算法将二叉树的二叉存储结构转换为顺序存储。

假设二叉树采用二叉链存储结构,设计一个算法求二叉树中节点值为 \(x\) 的节点层数。