已知二叉树的前序,中序,后序遍历中的两种求另外一种遍历

本文探讨了二叉树的前序、中序和后序遍历,解析了解决已知两种遍历方式求第三种遍历的方法。针对不同情况,如已知前序和中序、后序和中序,给出了详细解题步骤。同时指出,仅凭前序和后序遍历无法唯一确定中序遍历,除非额外提供树的特性信息。
  • 二叉树的遍历分为三种:
    1.前序遍历
    2.中序遍历
    3.后序遍历

  • 三种遍历的特征
    前序遍历:中左右
    中序遍历:左中右
    后序遍历:左右中

  • 根据已知的两种遍历方式求第三种,有三种组合方式

    • 第一种情况:已知前序遍历,中序遍历求后序遍历

      前序:ABDECFG 中序:DBEAFCG

    • 解法:
      前序的第一个节点就是根节点,     
      中序中找到根节点的位置,根节点之前是其左子树,之后是右子树    
      按此顺序,依次在左子树部分遍历,右子树部分遍历

    • 第二种情况:已知后序遍历,中序遍历求后序遍历

      后序:ABDECFG 中序:DBEAFCG

    • 解法:
      前序的第一个节点就是根节点,     
      中序中找到根节点的位置,根节点之前是其左子树,之后是右子树    
      按此顺序,依次在左子树部分遍历,右子树部分遍历

    • 第三种情况:已知前序遍历和后序遍历求中序遍历

      这种情况并不能完全的求出所有情况的二叉树中序遍历。因为由前序和后序并不能完全确定一颗树。但是,如果已知是满二叉树或者完全二叉树的话,我想是可以的。

      前序的第一个节点和后序的最后一个节点一定是根节点,如果前序的第二个节点与后序的倒数第二个节点不相等,那么前序的第二节点是根的左子树,后序的倒数第二节点是根的右子树(但是 如果前序的第二个节点与后序的倒数第二个节点相等,那就不能确定到底是左子树还是右子树了,因为缺省一个子树中左与左中,中右与右中都会相等。所以这就需要题目有要求该树的特征了)

二叉树前序、中后序遍历是信息学奥赛初赛中关于二叉树的重要知识点。 ### 遍历定义 - **前序遍历**:按照“根 - 左 - 右”的顺访问二叉树的节点,即先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。 - **中遍历**:按照“左 - 根 - 右”的顺访问节点,先递归地中遍历左子树,再访问根节点,最后递归地中遍历右子树。 - **后序遍历**:按照“左 - 右 - 根”的顺访问节点,先递归地后序遍历左子树,再递归地后序遍历右子树,最后访问根节点[^1]。 ### 遍历算法及特点 - **后序遍历的复杂性**:后序遍历相对麻烦,在“左右中”的遍历下,当遍历到栈顶时,难以判断是从左子树还是右子树返回的。对于叶子节点、右子树为 null 的节点以及从右子树遍历过来的情况,都需要打印当前栈顶节点,判断情况较为复杂[^2]。 ### 遍历转换 已知后序遍历结果,可以前序遍历。思路是利用后序遍历的最后一个字符是根节点,在中遍历中找到根节点的位置,将中遍历结果分为左右两个子串,再根据子串长度分割后序遍历列,最后递归解。以下是两种实现代码示例: ```cpp // 引用[1]代码示例 #include <iostream> #include <string> using namespace std; void dfs(string ldr, string lrd) { int len = lrd.length(); char root = lrd[len - 1]; cout << root; int root_index = 0; for(int i = 0; i < len; i++) { if(ldr[i] == root) { root_index = i; break; } } string ldr_left = ldr.substr(0, root_index); string ldr_right = ldr.substr(root_index + 1, len - root_index - 1); int len_left = ldr_left.length(); int len_right = ldr_right.length(); string lrd_left = lrd.substr(0, len_left); string lrd_right = lrd.substr(len_left, len - len_left - 1); if(len_left > 0) { dfs(ldr_left, lrd_left); } if(len_right > 0) { dfs(ldr_right, lrd_right); } } int main() { string ldr; string lrd; cin >> ldr; cin >> lrd; dfs(ldr, lrd); return 0; } ``` ```cpp // 引用[4]代码示例 #include <bits/stdc++.h> using namespace std; char mid[200], last[200]; void build(int x, int y, int p, int q) { if (x > y || p > q) return; int t = x; while (mid[t] != last[q]) t++; int len = t - x; cout << last[q]; build(x, t - 1, p, p + len - 1); // left build(t + 1, y, p + len, q - 1); // right } int main() { cin >> mid >> last; int size = strlen(mid) - 1; build(0, size, 0, size); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值