根据后序遍历(先序遍历)和中序遍历建树
今天来总结下二叉树前序、中序、后序遍历相互求法,即如果知道两个的遍历,如何求第三种遍历方法,比较笨的方法是画出来二叉树,然后根据各种遍历不同的特性来求,也可以编程求出。
首先: 我们看看先序、中序、后序遍历的特性
先序遍历:
① 访问节点
② 遍历左子树
③ 遍历右子树
中序遍历:
① 遍历左子树
② 访问节点
③ 遍历右子树
后序遍历:
① 遍历左子树
② 遍历右子树
③ 访问节点
对比三种遍历算法:只是访问顺序不同
分析:已知先序、中序遍历,求后序遍历
先序遍历: 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!