c++ 刷题 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。

  • Post author:
  • Post category:其他




题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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、根据第1、2步可得到根节点、左子树、右子树,接下来就是把左子树、右子树进行相同的操作

在这里插入图片描述



代码:

#include<iostream>
#include<vector>
using namespace std;

//Definition for binary tree 
struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};


TreeNode* reConstructBinaryTree(vector<int> &pre, vector<int> &vin) 
{
    //节点为空
    if (pre.empty())
        return NULL;

    int size = pre.size();
    //把根节点放到树里,注意,结构体的构造函数必须带一个值
    TreeNode* tree = new TreeNode(pre[0]);
    //只有一个节点
    if (size == 1)
    {
        return tree;
    }

    //找到中序遍历的根节点的下标:

    int inRoot = 0;
    for (; inRoot < size; ++inRoot)
        if (pre[0] == vin[inRoot])
            break;

    //把子树放到的相应数组里
    vector<int> preLeft, preRight, vinLeft, vinRight;
    for (int i = 1; i <= inRoot; ++i)
        preLeft.push_back(pre[i]);

    for (int i = inRoot + 1; i < size; ++i)
        preRight.push_back(pre[i]);

    for (int i = 0; i < inRoot; ++i)
        vinLeft.push_back(vin[i]);

    for (int i = inRoot + 1; i < size; ++i)
        vinRight.push_back(vin[i]);

    tree->left = reConstructBinaryTree(preLeft, vinLeft);
    tree->right = reConstructBinaryTree(preRight, vinRight);
    return tree;

}

//遍历顺序:根左右
void PreOrder(TreeNode* everyTreeNode)
{
	if (everyTreeNode)
	{
		cout << everyTreeNode->val << " ";
		PreOrder(everyTreeNode->left);
		PreOrder(everyTreeNode->right);
	}
}
//遍历顺序:左根右
void InOder(TreeNode* everyTreeNode)
{
	if (everyTreeNode)
	{

		InOder(everyTreeNode->left);
		cout << everyTreeNode->val << " ";
		InOder(everyTreeNode->right);
	}
}

int main()
{
	vector<int> pre = { 1, 2, 4, 7, 3, 5, 6, 8 };
	vector<int> vin = { 4,7,2,1,5,3,8,6 };

	TreeNode* tree = reConstructBinaryTree(pre, vin);
	
    cout << endl;
    cout << "先序遍历: " << endl;
	PreOrder(tree);
    cout << endl;
    cout << "中序遍历: " << endl;
    InOder(tree);

	return 0;
}



小结:

当然,我的代码可改进的地方还很多,比如不穿先序中序数组,而是传原始数组和左右子树的开始结束下标,这样就不必开辟新的空间存储子树数组的数据了。



大佬的代码:

在这里插入图片描述

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
         
        if(startPre>endPre||startIn>endIn)
            return null;
        TreeNode root=new TreeNode(pre[startPre]);
         
        for(int i=startIn;i<=endIn;i++)
            if(in[i]==pre[startPre]){
                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
                      break;
            }
                 
        return root;
    }
}



版权声明:本文为qq_45269116原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。