106从中序与后序遍历序列构造二叉树(递归)

1、题目描述

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

2、示例

中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

3、题解

基本思想:递归,不断以根节点拆分出左子树的后序中序和右子树的后序中序,继续递归,直至生成整棵树

  • 左子树的后序中序为postorder_left、inorder_left
  • 右子树的后序中序为postorder_right、inorder_right
  • 注意点:递归函数中传入指向指针的指针,这是因为空指针传参,代码把函数的第一个参数的值压入栈中存储,而空指针指向为空,不存在值*root,因此给*root一个临时变量和主函数并不是同一个*root
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
void PreOrderTraverse(TreeNode* T)
{
	if (T == NULL)
		return;
	cout << T->val << " ";
	PreOrderTraverse(T->left);
	PreOrderTraverse(T->right);

}
class Solution {
public:
	TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
		//简化版:递归,通过中序遍历序列找到根节点将中序遍历序列分割成左右子树,继续递归
		TreeNode* root = NULL;
		Recursion(inorder, postorder, root);
		return root;
	}
	void Recursion(vector<int> inorder, vector<int> postorder, TreeNode* &root)
	{
		if(inorder.size()==0)
			return;
		int i;
		for(i=0;i<inorder.size();i++)
		{
			if(inorder[i]==postorder[postorder.size()-1])
				break;
		}
		root=new TreeNode(postorder[postorder.size()-1]);
		Recursion(vector<int>(inorder.begin(),inorder.begin()+i),vector<int>(postorder.begin(),postorder.begin()+i),root->left);
		Recursion(vector<int>(inorder.begin()+i+1,inorder.end()),vector<int>(postorder.begin()+i,postorder.end()-1),root->right);
	}
};
class Solution1 {
public:
	TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
		//基本思想:递归,不断以根节点拆分出左子树的后序中序和右子树的后序中序,继续递归,直至生成整棵树
		//左子树的后序中序为postorder_left、inorder_left
		//右子树的后序中序为postorder_right、inorder_right
		if (postorder.size() == 0)
			return NULL;
		TreeNode* root = NULL;
		Recursion(inorder, postorder, &root);
		return root;
	}
	void Recursion(vector<int> inorder, vector<int> postorder, TreeNode** root)
	{
		int i, j;
		(*root) = new TreeNode(postorder[postorder.size() - 1]);
		//找到中序遍历的分隔点,也就是后序遍历的最后一个节点,将树拆分成左右子树
		for (i = 0; i < inorder.size(); i++)
		{
			if (inorder[i] == postorder[postorder.size() - 1])
				break;
		}
		vector<int> postorder_left, postorder_right;
		vector<int> inorder_left, inorder_right;
		//得到左子树的后序中序为postorder_left、inorder_left
		for (j = 0; j < i; j++)
		{
			postorder_left.push_back(postorder[j]);
			inorder_left.push_back(inorder[j]);
		}
		//得到右子树的后序中序为postorder_right、inorder_right
		for (j = i + 1; j < postorder.size(); j++)
		{
			postorder_right.push_back(postorder[j - 1]);
			inorder_right.push_back(inorder[j]);
		}
		//继续递归左右子树,直至生成整棵树
		if (postorder_left.size() > 0)
			Recursion(inorder_left,postorder_left, &(*root)->left);
		if (postorder_right.size() > 0)
			Recursion(inorder_right,postorder_right, &(*root)->right);
	}
};
int main()
{
	Solution solute;
	vector<int> inorder = { 3,9 };
	vector<int> postorder = { 3,9 };
	TreeNode* root = solute.buildTree(inorder, postorder);
	PreOrderTraverse(root);
	return 0;
}

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值