题目链接二叉树遍历
题目大意为给出字符串树的前序和中序遍历,求出其后序遍历。
方法一:这个方法是我参考《挑战程序竞赛–数据结构》上的方法写出的。
思路为根据递归遍历树的原理,在重建树的过程中直接存下后序遍历,因为可以有前序和中序遍历每次确定一个根节点,则递归遍历其左子树和右子树,最后存下根节点,整个过程类似后序遍历。
但代码使用了distance和find函数,具体参考博客acm之旅–树。
代码如下:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int MAX = 30;
int ind, n;
vector<char> pre, in, post;
void rec(int l, int r)//重建树
{
if(l>=r) return;
char root = pre[ind++];
int m = distance(in.begin(), find(in.begin(), in.end(), root));
rec(l, m);
rec(m+1, r);
post.push_back(root);//存下后序遍历
}
void solve()
{
ind = 0;
n = pre.size();
rec(0, n);
for(int i=0; i<n; i++)
{
cout << post[i];
}
cout << endl;
}
int main()
{
char x[MAX], y[MAX];
while(gets(x))
{
gets(y);
for(int i=0; i<strlen(x); i++)
{
//cout << x[i] << endl;
pre.push_back(x[i]);
}
for(int i=0; i<strlen(y); i++)
{
in.push_back(y[i]);
}
solve();
post.clear();
pre.clear();
in.clear();
}
return 0;
}
方法二:此方法为书中的方法,具体为先重建出原树,再后序遍历这个树。
重点掌握建立树的数据结构。
代码如下:
#include <cstdio>
#include <cstring>
struct Node
{
Node *lchild;
Node *rchild;
char c;
};
Node Tree[50];
int loc;
Node *creat()//申请一个结点空间,返回指向其的指针
{
Tree[loc].lchild = Tree[loc].rchild = NULL;
return &Tree[loc++];
}
char str1[30], str2[30];
void postOrder(Node *T)
{
if(T->lchild!=NULL) postOrder(T->lchild);
if(T->rchild!=NULL) postOrder(T->rchild);
printf("%c", T->c);
}
Node *build(int s1, int e1, int s2, int e2)
{
Node *ret = creat();
ret->c = str1[s1];//将新建的结点值赋值为前序遍历的第一个字符,即根
int rootIdx;
for(int i=s2; i<=e2; i++)//查找根节点字符在中序遍历中的位置
{
if(str2[i]==str1[s1])
{
rootIdx = i;
break;
}
}
if(rootIdx!=s2)
ret->lchild = build(s1+1, s1+(rootIdx-s2), s2, rootIdx-1);//注意下标的计算
if(rootIdx!=e2)
ret->rchild = build(s1+(rootIdx-s2)+1, e1, rootIdx+1, e2);
return ret;
}
int main()
{
while(scanf("%s", str1)!=EOF)
{
scanf("%s", str2);
loc = 0;
int L1 = strlen(str1);
int L2 = strlen(str2);
Node *T = build(0, L1-1, 0, L2-1);
postOrder(T);
printf("\n");
}
return 0;
}