输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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},则重建二叉树并返回。
分析:
- 根据先序遍历序列第一个节点确定根节点。
- 根据根节点在中序遍历序列中分割出左右两个字符。
- 对左子树和右子树跟别递归使用相同的办法继续分解
- 先序遍历的第二个元素是左子树的第二个根。
举例:
- 前序遍历:ABCDEFGHK
- 中序遍历:BDCAEHGKF
- 后续遍历:DCBHKGFEA
此时我们挑出前序和中序遍历,由于前序遍历先访问头节点,所以可以得到A是我们的根节点,由此我们到中序遍历中可以发现A的左侧是左子树(BDC),A的右侧是右子树(EHGKF),继而推导出前序遍历的元素分界点,使用递归的思想,我们再次从头分析,由前序遍历的左子树(BCD)中我们可以推导出B是左子树的根节点,把B放入中序遍历中,再次分解,左子树(没有),右子树(DC)。再次递归前序遍历中C为B左子树的头节点,放入中序遍历C的左子树(空)右子树(A),依次我们可以推荐出根节点的右子树,同样是递归的方法。
注意点:
- 任意一个二叉树给了中序遍历,并给了前序或者后序,都可以找到同一个二叉树。
- 如果没有中序遍历,是不能确定唯一一个二叉树的。
代码如下:
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; }};
参考博客链接:
- https://www.cnblogs.com/zhuifengshaonian/p/10102931.html(重建二叉树的实现参考)
- https://blog.csdn.net/qq_33243189/article/details/80222629(二叉树的前序中序后序遍历参考)