二叉树遍历与构造
二叉树的遍历
二叉树遍历其实很简单,三种遍历都是一样的,只不过顺序先后不一样罢了。
先序遍历
访问根结点,先序遍历左子树,先序遍历右子树
void PreOrder(BitTree T){
if( T != nullptr){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}中序遍历
中序遍历左子树,访问根结点,中序遍历右子树
void InOrder(BitTree T){
if(T != nullptr){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}后序遍历
后序遍历左子树,后序遍历右子树,访问根结点
时间复杂度都为O(n),在递归遍历中,递归工作栈的栈深恰好为树的深度,在最坏情况下,二叉树是有n个结点且深度为 n 的单支树,遍历算法的空间复杂度为O(n)。
利用非递归方式遍历二叉树
借助栈,可以将二叉树的递归遍历转换为非递归算法。以中序遍历为例,给出中序遍历非递归算法。先扫描(并非访问)根结点的所有左结点并将它们一一进栈,然后出栈一个结点*p,访问它。然后继续扫描该结点的右孩子结点,将其进栈,在扫描该孩子结点的所有左结点并一一进栈,如此继续,直到栈空。
中序遍历的非递归算法如下:
前序遍历的非递归算法:
后序遍历的非递归算法:后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。直接看代码,代码中有详细的注释。
层次遍历
层次遍历需要借助队列。先将二叉树根结点入队,然后初岁,访问该结点,若它有左子树,则将左子树根节点入队;若它有右子树,则将右子树根结点入队。然后出队,对出队结点访问,如此反复,直到队列为空。

由遍历序列构造二叉树
由二叉树的先序和中序序列可以唯一确定一棵二叉树,同样后序和中序序列也可以唯一确定一棵二叉树,但先序和后序不能确定一棵二叉树。
先序和中序序列构造一棵二叉树
思路:我们知道先序序列的第一个值其实就是根节点的值,这样我们就可以在中序序列中找到对应的根节点,那么根节点左边的数就全为左子树的结点,根节点右边的数就全为右子树的结点。根据这个想法,再递归的进行构造,见代码。
后序和中序序列构造一棵二叉树
思路:我们知道后序序列的最后一个值其实就是根节点的值,这样我们就可以在中序序列中找到对应的根节点,那么根节点左边的数就全为左子树的结点,根节点右边的数就全为右子树的结点。根据这个想法,再递归的进行构造,见代码。
Last updated
Was this helpful?