还原的要点是:根据后序序列的特点,知道根节点处于后序序列的最后一个节点,然后根据节点值,在中序序列中找到此根节点的位置,这样就知道中序序列的左右子树位置,左子树区间从左侧直到此根节点的前一个节点,右子树区间从此根节点的右侧直到区间右边界,然后对左右子树依次递归即可。
同理,前序序列中,首节点就是整个树的根节点,根据根节点在中序序列中找到根节点的位置,然后将中序序列空间分为左右子树区间,依次递归。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <queue>
using namespace std;
const int maxn = 30;
int postOrder[maxn] = { 0 };
int inOrder[maxn] = { 0 };
struct node {
int data;
node* lchild;
node* rchild;
};
// 根据后序序列和中序序列还原一棵二叉树
node* create(int postL, int postR, int inL, int inR) {
if (postL > postR) return nullptr;
node* root = new node;
root->data = postOrder[postR];
int k;
for (k = inL; k <= inR; ++k) {
if (inOrder[k] == postOrder[postR]) {
break; // 在中序区间中找到了根节点的位置
}
}
int numLeft = k - inL; // 偏移量
// 注意此处对左子树区间和右子树区间的划分,根据关键的偏移量来划分的结果
root->lchild = create(postL, postL + numLeft - 1, inL, k - 1);
root->rchild = create(postL + numLeft, postR - 1, k + 1, inR);
return root;
}
// 层序遍历
void LayerOrder(node* root) {
queue<node*> q;
q.push(root);
bool isFirstNode = true;
while (!q.empty()) {
node* top = q.front();
q.pop();
if (isFirstNode) {
printf("%d", top->data);
isFirstNode = false;
}
else {
printf(" %d", top->data);
}
if (top->lchild != nullptr) q.push(top->lchild);
if (top->rchild != nullptr) q.push(top->rchild);
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) scanf("%d", &postOrder[i]);
for (int i = 0; i < n; ++i) scanf("%d", &inOrder[i]);
LayerOrder(create(0, n - 1, 0, n - 1));
return 0;
}
输入:
第一行是节点总数
第二行是后序序列
第三行是中序序列
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出:
输出为对整个树进行层序遍历的结果
4 1 6 3 5 7 2
谢谢阅读