输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

分析:

  1. 根据先序遍历序列第一个节点确定根节点。
  2. 根据根节点在中序遍历序列中分割出左右两个字符。
  3. 对左子树和右子树跟别递归使用相同的办法继续分解
  4. 先序遍历的第二个元素是左子树的第二个根。

举例:

      输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

  1. 前序遍历:ABCDEFGHK
  2. 中序遍历:BDCAEHGKF
  3. 后续遍历:DCBHKGFEA

此时我们挑出前序和中序遍历,由于前序遍历先访问头节点,所以可以得到A是我们的根节点,由此我们到中序遍历中可以发现A左侧是左子树(BDC),A的右侧是右子树(EHGKF),继而推导出前序遍历的元素分界点,使用递归的思想,我们再次从头分析,由前序遍历的左子树(BCD)中我们可以推导出B是左子树的根节点,把B放入中序遍历中,再次分解,左子树(没有),右子树(DC)。再次递归前序遍历中C为B左子树的头节点,放入中序遍历C的左子树(空)右子树(A),依次我们可以推荐出根节点的右子树,同样是递归的方法。

注意点:

  1. 任意一个二叉树给了中序遍历,并给了前序或者后序,都可以找到同一个二叉树。
  2. 如果没有中序遍历,是不能确定唯一一个二叉树的。 

代码如下:

 1 /*struct TreeNode {
 2 int val;
 3 TreeNode *left;
 4 TreeNode *right;
 5 TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 6 };*/
 7 class Solution {
 8 public:
 9 TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
10 int size = pre.size();
11 if(size == 0)
12 return NULL;
13 vector<int> pre_left,vin_left,pre_right,vin_right;
14 TreeNode* header = new TreeNode(pre.at(0));
15 int index = 0;//中间结点的下标
16 for(int i = 0;i < size;i++)
17 {
18 if(header->val == vin.at(i))
19 index = i;
20 }
21 //把左右分支分别复制给pre_left,vim_left,pre_right,pre_right;
22 for(int i = 0; i < size; i++)
23 {
24 if(i<index)
25 {vin_left.push_back(vin.at(i));
26 pre_left.push_back(pre.at(i+1));}
27 else if(i>index)
28 {vin_right.push_back(vin.at(i));
29 pre_right.push_back(pre.at(i));}
30 }
31 header->left = reConstructBinaryTree(pre_left,vin_left);
32 header->right = reConstructBinaryTree(pre_right,vin_right); return header; }};

参考博客链接:

  1. https://www.cnblogs.com/zhuifengshaonian/p/10102931.html(重建二叉树的实现参考)
  2. https://blog.csdn.net/qq_33243189/article/details/80222629(二叉树的前序中序后序遍历参考)