根据后序遍历(先序遍历)和中序遍历建树
今天来总结下二叉树前序、中序、后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出。
首先: 我们看看先序、中序、后序遍历的特性
先序遍历:
① 访问节点
② 遍历左子树
③ 遍历右子树
中序遍历:
① 遍历左子树
② 访问节点
③ 遍历右子树
后序遍历:
① 遍历左子树
② 遍历右子树
③ 访问节点
对比三种遍历算法:只是访问顺序不同
分析:已知先序、中序遍历,求后序遍历
先序遍历: GDAFEMHZ
中序遍历: ADEFGHMZ
🔥 根据前序遍历的特点,我们知道根结点为G
🔥 观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树,G右侧的HMZ必然是root的右子树。
🔥 观察左子树ADEF,左子树的中的根节点必然是大树的root的leftchild。在前序遍历中,大树的root的leftchild位于root之后,所以左子树的根节点为D。
🔥 同样的道理,root的右子树节点HMZ中的根节点也可以通过前序遍历求得。在前序遍历中,一定是先把root和root的所有左子树节点遍历完之后才会遍历右子树,并且遍历的左子树的第一个节点就是左子树的根节点。同理,遍历的右子树的第一个节点就是右子树的根节点。
🔥 观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了。该步递归的过程可以简洁表达如下:
① 确定根,确定左子树,确定右子树
② 在左子树中递归
③ 在右子树中递归
代码:以下是建树代码实现并遍历
🍀 后序和中序
#include <bits/stdc++.h>
using namespace std;
typedef struct TreeNode {
int data;
struct TreeNode *left, *right;
} TreeNode;
int post[100], in[100];
/*
input
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
output
4 1 6 3 5 7 2
*/
TreeNode* buildTree(int root, int start, int end) {
if (start > end)
return NULL;
int i = end;
while (i > start && in[i] != post[root]) i--;
TreeNode* t = new TreeNode();
t->data = post[root];
t->left = buildTree(root - 1 + i - end, start, i - 1);
t->right = buildTree(root - 1, i + 1, end);
return t;
}
void bfs(TreeNode* T) {
queue<TreeNode> qu;
qu.push(*T);
TreeNode p;
int first = 1;
while (!qu.empty()) {
p = qu.front();
qu.pop();
if (first) {
printf("%d", p.data);
first = 0;
} else
printf(" %d", p.data);
if (p.left)
qu.push(*(p.left));
if (p.right)
qu.push(*(p.right));
}
}
int main() {
int N;
cin >> N;
for (int i = 0; i < N; i++)
cin >> post[i];
for (int i = 0; i < N; i++)
cin >> in[i];
TreeNode* tree = buildTree(N - 1, 0, N - 1);
bfs(tree);
putchar(10);
system("pause");
return 0;
}
🍀 先序和中序(和后序同理)
#include <bits/stdc++.h> using namespace std; typedef struct TreeNode { int data; struct TreeNode *left, *right; } TreeNode; int pre[100], in[100]; /* input 6 1 2 3 4 5 6 3 2 4 1 6 5 output 1 2 5 3 4 6 */ TreeNode* buildTree(int root, int start, int end) { if (start > end) return NULL; int i = start; while (i < end && in[i] != pre[root]) i++; TreeNode* t = new TreeNode(); t->data = pre[root]; t->left = buildTree(root + 1, start, i - 1); t->right = buildTree(root + 1 + i - start, i + 1, end); return t; } void bfs(TreeNode* T) { queue<TreeNode> qu; qu.push(*T); TreeNode p; int first = 1; while (!qu.empty()) { p = qu.front(); qu.pop(); if (first) { printf("%d", p.data); first = 0; } else printf(" %d", p.data); if (p.left) qu.push(*(p.left)); if (p.right) qu.push(*(p.right)); } } int main() { int N; cin >> N; for (int i = 0; i < N; i++) cin >> pre[i]; for (int i = 0; i < N; i++) cin >> in[i]; TreeNode* tree = buildTree(0, 0, N - 1); bfs(tree); putchar(10); system("pause"); return 0; }

根据中序后序序列建树,先从后序序列中去挑选根节点存入树中,再遍历中序序列找到根节点,根据找到的根节点位置去划分出左右子树。关键就是如何找到每次的根节点,以及如何确定出中序序列的遍历范围。
浙公网安备 33010602011771号