重构二叉树(前序遍历和中序遍历)

二叉树的前序遍历是先遍历根节点,接着是左子树节点,最后是右子树节点,所以可以通过前序遍历确定树的根节点。
二叉树的中序遍历实现遍历二叉树的左子树节点,接着是根节点,最后是右子树节点,所以可以通过中序遍历找到根节点后,根节点左边的节点是左子树节点,根节点右边的节点是右子树节点。

利用上述两个理论就可以在知道前序遍历和中序遍历的情况下重构二叉树。
给定一棵树的前序遍历序列:1,2,3,4,5,6;
中序遍历序列:3,2,4,1,6,5。
这里写图片描述

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size()==0||vin.size()==0)
        {
            return NULL;
        }
        int* pre_begin=&pre[0];
        int* pre_end=&pre[pre.size()-1];
        int* vin_begin=&vin[0];
        int* vin_end=&vin[vin.size()-1];
        //实际传进来的前两个参数是左右子树的开始节点,结束节点;
        //每构造一个节点,中序序列中指向根节点的指针向前移一个,
        //所以后两个参数是为了确定leftlen,为在前序序列中构造节点做基础。
        return _reConstructBinaryTree(pre_begin,pre_end,vin_begin,vin_end);
    }
    TreeNode* _reConstructBinaryTree(int* pre_begin,int* pre_end,int* vin_begin,int* vin_end)
    {
        TreeNode* root=new TreeNode(pre_begin[0]);
        root->left=root->right=NULL;
        //只有一个节点的情况
        if(pre_begin==pre_end&&vin_begin==vin_end&&*pre_begin==*vin_begin)
        {
            return root;
        }
        //在中序序列中找根节点,找到就break,当前指针就指向根节点
        int* cur=vin_begin;
        for(;cur<vin_end;++cur)
        {
            if(*cur==*pre_begin)
            {
                break;
            }
        }
        //确定左子树的长度和左子树的最后节点,构造左子树,右子树
        int leftlen=cur-vin_begin;
        int* left_pre_end=pre_begin+leftlen;
        if(leftlen>0)
        {
            root->left=_reConstructBinaryTree(pre_begin+1,left_pre_end,vin_begin,cur-1);
        }
        if(leftlen<pre_end-pre_begin)
        {
            root->right=_reConstructBinaryTree(left_pre_end+1,pre_end,cur+1,vin_end);
        }
        return root;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_39295755/article/details/79772803