根据先序遍历和中序遍历生成二叉树

本文介绍了一种通过先序遍历和中序遍历序列来重构原始二叉树的方法,并给出了具体的实现步骤及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:先序遍历为1,2,4,7,3,5,6,8,中序遍历为4,7,2,1,5,3,8,6,根据以上遍历序列生成原来的二叉树。
思路:先序遍历的第一个节点为1,即头节点为1,找到头节点1在中序遍历中的位置,根据中序遍历的特点,可以知道头节点1左边的序列是位于左子树上的节点,头节点1右边的序列是位于右子树上的节点,于是构造头节点1,得到头节点左子树的中序遍历序列为4,7,2,总共3个数,那么说明左子树的先序遍历数字也应该有3个,根据先序遍历为VLR,在先序遍历头节点1后面的3个节点为左子树的先序遍历序列,这个序列为2,4,7,而剩下的序列为右子树上先序遍历的顺序,其右边节点的中序遍历为3,5,6,8。于是将该问题划分为两个字问题:

从先序遍历为2,4,7,中序遍历为4,7,2构造一个子树作为根节点的左子树。
从先序遍历为3,5,6,8,中序遍历为5,3,8,6构造一个子树作为根节点的右子树。
构造子树的过程重复以上构造过程即可,直到遍历序列为空则返回空指针
二叉树节点构造如下:

//二叉树节点定义
template<typename T>struct BTNode
{
public:
    BTNode(const T& v=0):data(v),left(nullptr),right(nullptr){}
    BTNode():data(0),left(nullptr),right(nullptr){}
    BTNode<T>* left,right;
    T data;
};
//寻找下标函数
template<typename T>
int findIndex(const T& num,const vector<T>& srcVec)
{
    for(int i = 0;i!=srcVec.size();++i)
        if(srcVec[i]==num)
            return i;
    return -1;
}

//按照层序遍历打印树上的节点
template<typename T>
void levelVisitBinaryTree(BTNode<T>* root)
{
    if(root==nullptr)
        return;
    queue<BTNode<T>*> myQueue;
    myQueue.push(root);
    while(!myQueue.empty())
    {
        BTNode<T>* r=nullptr;
        while(!myQueue.empty())
        {
            r = myQueue.front();
            cout<<r->data<<" ";
            myQueue.pop();
            if(r->left)
                myQueue.push(r->left);
            if(r->right)
                myQueue.push(r->right);
        }
        cout<<endl;
    }
}

//根据先序遍历和中序遍历构造二叉树
template<typename T>
 BTNode<T>* createBinaryTree(vector<T>& preOrder,vector<T>& inOrder)
{
    if(preOrder.size()==0||inOrder.size()==0)
        return nullptr;
    //findIndex函数找到头节点在中序遍历中的下标
    int rootIndex = findIndex(preOrder[0],inOrder);
    BTNode<T>* root=new BTNode<T>(preOrder[0]);//构造根节点
    if(rootIndex>=0)
    {
        BTNode<T>* left=nullptr,*right=nullptr;//左子树和右子树

        vector<T> leftPreOrder;//左子树先序遍历序列
        vector<T> leftInOrder;//左子树中序遍历序列
        if(rootIndex>0)
        {
            //构造左子树的先序遍历序列
            leftPreOrder.assign(preOrder.begin()+1,
            preOrder.begin()+rootIndex+1);
            //构造左子树的中序遍历序列
            leftInOrder.assign(inOrder.begin(),
            inOrder.begin()+rootIndex);
            //根据先序和中序构造左子树
            left = createBinaryTree(leftPreOrder,leftInOrder);
        }

        vector<T> rightPreOrder;//右子树先序遍历序列
        vector<T> rightInOrder;//右子树中序遍历序列
        if(static_cast<int>(rootIndex)<preOrder.size()-1)
            //构造右子树的先序遍历序列
            rightPreOrder.assign
            (preOrder.begin()+rootIndex+1,preOrder.end());
        if(static_cast<int>(rootIndex)<inOrder.size()-1)
            //构造右子树的中序遍历序列
            rightInOrder.assign
            (inOrder.begin()+rootIndex+1,inOrder.end());
        //根据先序和中序构造右子树
        right= createBinaryTree(rightPreOrder,rightInOrder);
        //left和right赋值给root
        root->left = left;
        root->right = right;
    }
return root;
}

//以下代码用于测试
int main()
{
    vector<int> preOrder;
    int a[]={1,2,4,7,3,5,6,8};
    preOrder.assign(begin(a),end(a));
    vector<int> inOrder;
    int b[]={4,7,2,1,5,3,8,6};
    inOrder.assign(begin(b),end(b));
    BTNode<int>* root = createBinaryTree(preOrder,inOrder);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值