#include <iostream>
using namespace std;
const int N = 1010;
int pre[N], in[N], post[N];
int k;
struct node {
int value;
node* l, * r;
node(int value = 0, node* l = NULL, node* r = NULL) : value(value), l(l), r(r) {}
};
// 递归建树
//需要参数 root当前需要新建的根节点 t即为当前根节点的位置
//node*& root中 传递的是若仅传递指针,传递的是指针的副本,函数内部对该副本的修改不会影响到外部原指针。
//而使用指针的引用时,可以直接修改指针本身,使其指向新的节点
//重点:理解前序遍历的顺序是根左右
void prebuildtree(int l, int r, int& t, node*& root) {
if (l > r)
return;
int flag;
for (int i = l; i <= r; i++) {
if (pre[t] == in[i]) {
flag = i;
break;
}
}
root = new node(pre[t]);
t++;
prebuildtree(l, flag - 1, t, root->l);
prebuildtree(flag + 1, r, t, root->r);
}
//与本题无关只是练手
void postbuildtree(int l, int r, int& t, node*& root) {
if (l > r) return;
int flag;
for (int i = l; i <= r; i++)
{
if (post[t] == in[i])
{
flag = i;
break;
}
}
root = new node(in[flag]);
t--;
postbuildtree(flag + 1, r, t, root->r);
postbuildtree(l, flag-1, t, root->l);
}
void preorder(node* root) {
if (root != NULL) {
pre[k++] = root->value;
preorder(root->l);
preorder(root->r);
}
}
void inorder(node* root) {
if (root != NULL) {
inorder(root->l);
in[k++] = root->value;
inorder(root->r);
}
}
void postorder(node* root) {
if (root != NULL) {
postorder(root->l);
postorder(root->r);
post[k++] = root->value;
}
}
void remove_tree(node* root) {
if (root == NULL) return;
remove_tree(root->l);
remove_tree(root->r);
delete root;
}
int main() {
int n;
while (cin >> n && n != 0) {
for (int i = 0; i < n; i++)
cin >> pre[i];
for (int j = 0; j < n; j++)
cin >> in[j];
node* root = NULL;
int t = 0;
prebuildtree(0, n - 1, t, root);
k = 0;
postorder(root);
for (int i = 0; i < k; i++)
cout << post[i] << " ";
cout << endl;
remove_tree(root);
}
return 0;
}
本题的关键是理解先序和中序建树 还有中序和后序建树 网上的很多教程都没有讲清楚
先序和中序建树:
关键点在于理解函数的四个参数
l,r:当前利用先序的根节点搜索左右子树的范围来判断结束条件
t:根据先序 根左右来建树 每次新增的结点都是先序遍历顺序的结点
* &root:注意&否则传递的只是地址值 改变地址 没有改变本身的地址
后序和中序建树:
这里我们要注意的是 先序和中序建树是按照先序的顺序正向建树
但后序不能正向进行 因为最后建设根节点 先建设左右节点这是不可能的
所以要倒序 从根建立 左右根 变为 根右左 同时t--即可成功构建