二叉树遍历(九度教程第 32 题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否
时间限制:1 秒 内存限制:32 兆 特殊判题:否
1.题目描述:
二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。
输入:
两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C….最多26个结点。
输出:
输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。
样例输入:
ABC
BAC
FDXEAG
XDEFAG
样例输出:
BCA
XEDGAF
2.基本思路
根据前序遍历和中序遍历的结果便可以唯一的确定二叉树的结构,即可以得到该二叉树的后序遍历的结果。存在如下规律:根据前序遍历结果的第一个字符可以得到二叉树的根结点,然后通过在中序遍历中找到对应的结点刚好将字符分为两段,左边为左子树,右边为右子树。然后再根据划分的结果在前序遍历中按照上述的思路确定左子树和右子树的根结点,以此反复便可以构造整颗二叉树。然后再对构造完的二叉树进行后序遍历便可以得到最终的结果。
3.代码实现
利用后序遍历和中序遍历的结果同样也可以得到前序遍历的结果,基本原理是一样的。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Node{
Node* lchild;
Node* rchild;
char c;
}Tree[50];
int loc=0;
Node* create(){//申请一个结点空间并进行初始化同时返回指向该结点的指针
Tree[loc].lchild = NULL;
Tree[loc].rchild = NULL;
loc++;
return &Tree[loc];
}
char str1[30],str2[30];
Node* build(int s1,int e1,int s2,int e2){//由前序遍历和中序遍历的字符串构造二叉树并返回其根结点
Node* root = create();//申请一个根结点
root->c = str1[s1];//根结点的值为前序遍历的第一个字符
int rootidx=0;//记录前序遍历的第一个字符在中序遍历中的位置
for(int i=s2;i<=e2;i++){
if(str2[i]==str1[s1]){
rootidx = i;
break;
}
}
if(rootidx!=s2){//若左子树不为空.递归还原左子树
root->lchild = build(s1+1,s1+(rootidx-s2),s2,rootidx-1);
}
if(rootidx!=e2){//若右子树不为空,递归还原右子树
root->rchild = build(s1+(rootidx-s2)+1,e1,rootidx+1,e2);
}
return root;//返回根结点指针
}
Node* build1(int s1,int e1,int s2,int e2){//由后序遍历和中序遍历的字符串构造二叉树并返回其根结点
Node* root = create();//申请一个根结点
root->c = str1[e1];//根结点的值为前序遍历的第一个字符
int rootidx=0;//记录前序遍历的第一个字符在中序遍历中的位置
for(int i=s2;i<=e2;i++){
if(str2[i]==str1[e1]){
rootidx = i;
break;
}
}
if(rootidx!=s2){//若左子树不为空.递归还原左子树
root->lchild = build(s1,s1+(rootidx-s2)-1,s2,rootidx-1);
}
if(rootidx!=e2){//若右子树不为空,递归还原右子树
root->rchild = build(s1+(rootidx-s2),e1-1,rootidx+1,e2);
}
return root;//返回根结点指针
}
void postOrder(Node *r){//二叉树的后序遍历
if(r->lchild!=NULL){//左子树不为了空遍历左子树
postOrder(r->lchild);
}
if(r->rchild!=NULL){//右子树不为空遍历右子树
postOrder(r->rchild);
}
printf("%c",r->c);
}
void preOrder(Node *r){//二叉树的前序遍历
printf("%c",r->c);
if(r->lchild!=NULL){//左子树不为了空遍历左子树
postOrder(r->lchild);
}
if(r->rchild!=NULL){//右子树不为空遍历右子树
postOrder(r->rchild);
}
}
int main()
{
while(scanf("%s",str1)!=EOF){
scanf("%s",str2);
loc=0;//初始分配的空间为大小为0
int L1=strlen(str1);
int L2=strlen(str2);
// Node *root = build(0,L1-1,0,L2-1);
// postOrder(root);
Node *root = build(0,L1-1,0,L2-1);
postOrder(root);
printf("\n");
}
return 0;
}
/*
ABC
BAC
FDXEAG
XDEFAG
BCA
BAC
XEDGAF
XDEFAG
ABC
FDXEAG
*/