问题:
已知二叉树的前序和中序遍历结果,重建二叉树。
分析与解法:
- 初始:用前序遍历序列确定根节点,在中序遍历序列中找到该根节点,则左右子树分别为中序中该节点左右的序列。
- 迭代:对各个子树分别执行三步操作,1.在前序序列中找子树的根节点;2。在中序序列中找子树的根节点,并划分开根节点的左右子树;3.根据新生成的左右子树,在前序序列中划分开这些节点,从而得到了两颗子树的前序、中序序列。
代码:
typedef struct Node
{
struct Node *lchild, *rchild;//指向左右子树的指针
char cdata; //节点数值
}Node, *BiTree;
//前序+中序
void rePreInBuild(BiTree &T,//重建的二叉树
char *preOrder,//前序遍历序列
char *inOrder, //中序遍历序列
int n) //二叉树的节点个数
{
//判断边界条件
if(preOrder == NULL || inOrder == NULL || n == 0)
return;
//获取根节点
T = new Node;
T -> cdata = *preOrder;
T -> lchild = NULL;
T -> rchild = NULL;
//查找根节点在中序遍历序列中的位置
int i;
for(i = 0; i < n && *(inOrder + i) != T -> cdata; i++);
int llen = i;//左子树节点的个数
int rlen = n - i - 1;//右子树节点的个数
if(llen > 0)//重建左子树
rePreInBuild(T -> lchild, preOrder + 1, inOrder, llen);
if(rlen > 0)//重建右子树
rePreInBuild(T -> rchild, preOrder + llen + 1, inOrder + llen + 1, rlen);
}
思考:
已知二叉树的后序和中序遍历结果,重建二叉树。解法同上。
已知二叉树的层序和中序遍历结果,重建二叉树。
- 初始:用层序遍历确定顶节点,在中序遍历中,利用顶节点划分出左右子树。
- 迭代:对各个子树分别执行三步操作,1.在层序序列中,找出子树节点集合中,最靠前的节点,这个节点即为子树的顶节点;2.在中序序列中找 1 中得到的顶节点,并划分开顶节点的左右子树。
- 跟(中序+前序)和(中序+后序)不同.之处在于没有迭代的第 3 步,层序是无法直接划分得到左右子树的节点集合的。但这并不妨碍正常的处理。层序是用来找到子树的顶节点的,而顶节点即是所有子树的节点中,在层序遍历中最靠前的节点。
代码:
//后序+中序
void rePostInBuild(BiTree &T, char *postOrder, char *inOrder, int n)
{
if(postOrder == NULL || inOrder == NULL || n == 0)
return;
T = new Node;
T -> cdata = *(postOrder + n - 1);
T -> lchild = NULL;
T -> rchild = NULL;
int i;
for(i = 0; i < n && *(inOrder + i) != T -> cdata; i++);
int llen = i;
int rlen = n - i - 1;
if(llen > 0)
rePostInBuild(T -> lchild, postOrder, inOrder, llen);
if(rlen > 0)
rePostInBuild(T -> rchild, postOrder + llen, inOrder + llen + 1, rlen);
}
扩展问题:
- 如果前序和中序遍历的字母有重复的,那么怎么构造所有可能的解呢?
- 如何判断给定的前序遍历和中序遍历的结果是合理的?
http://blog.csdn.net/vividonly/article/details/6688327
文章参考以下博文:
http://blog.csdn.net/luyafei_89430/article/details/12967411
http://blog.csdn.net/yunzhongguwu005/article/details/9270085