通过树的先序和中序遍历序列来构造二叉树

题目:给出一棵二叉树的先序和中序遍历的序列,构造出该二叉树。

思路一:采用分治法。

1)取先序遍历序列的第一个值,用该值构造根结点,,然后在中序遍历序列中查找与该元素相等的值,这样就可以把序列分为三部分:左子树(如果有)、根结点和右子树(如果有)。

2)将两个序列都分成三部分,这样就分别形成了根结点的左子树和右子树的先序遍历和后序遍历的序列。

3)重复1)和2)步骤,直至所有结点都处理完就可以完整构成一颗二叉树了。

根据分治法构造二叉树的代码实现:

TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder)
{
        if(preorder.empty() && inorder.empty())
            return NULL;
        int root_val = preorder[0];//该子树根结点的元素值为先序遍历的第一个元素
        TreeNode* root = new TreeNode(root_val);//创建该子树的根结点
        vector<int> preorderL, preorderR, inorderL, inorderR;
        vector<int>::iterator it, it_a;//在中序遍历中查找根结点元素
        int i = 0;
        it = inorder.begin();
        while(*it != root_val)
        {
            it++;
            i++;
        }

        //确定中序遍历的左右子树序列
        for(it_a = inorder.begin(); it_a != it; it_a++)
            inorderL.push_back(*it_a);
        for(it_a = it+1; it_a != inorder.end(); it_a++)
            inorderR.push_back(*it_a);
        //确定前序遍历的左右子树序列
        it = preorder.begin();
        while(i)
        {
            it++;
            i--;
        }

        for(it_a = preorder.begin()+1; it_a != it+1; it_a++)
            preorderL.push_back(*it_a);
        for(it_a = it+1; it_a != preorder.end(); it_a++)
            preorderR.push_back(*it_a);

        //迭代构造二叉树
        root->left = buildTree(preorderL, inorderL);
        root->right = buildTree(preorderR, inorderR);

        return root;
}

这段代码在OJ里运行就报错了Status: 
Memory Limit Exceeded
。具体原因我现在也没搞明白……

思路二:用栈来实现。

1)用先序遍历序列中的第一个元素构造树的根结点,并将根结点指针入栈。

2)如果栈顶结点的元素值与中序遍历序列当前处理的元素值不相等,则一直用先序遍历序列中的元素构造树结点,如果flag标志值为0,将新结点添加为树当前处理结点的左孩子结点;否则,添加为右孩子结点。

3)如果栈顶结点的元素值与中序遍历序列当前处理的元素值相等,则将栈顶结点置为树的当前处理结点,然后将该结点出栈,并将flag标志置为1.

4)重复2)和3)的操作,直到先序遍历序列处理完。

用栈来实现构造二叉树的代码实现:

TreeNode *buildTree1(vector<int> &preorder, vector<int> &inorder)
{

    if(preorder.size()==0)
        return NULL;

    stack<TreeNode *> st;
    TreeNode *t, *root;
    int i, j;//i,j分别作为前序和中序遍历序列的处理指针
    int f;//用于标识是否要新建右结点

    f = i = j = 0;

    root = new TreeNode(preorder[i]);
    st.push(root);
    t = root;
    i++;

    while(i<preorder.size())
    {
        //case 1:栈顶结点的元素值与中序遍历当前值相等
        if(!st.empty() && st.top()->val == inorder[j])
        {
            t = st.top();
            st.pop();
            f = 1;
            j++;
        }
        else
        {
            //case 2a:f = 0,添加左结点
            if(f == 0)
            {
                t -> left = new TreeNode(preorder[i]);
                t = t -> left;
                st.push(t);
                i++;
            }
            //case 2b:f = 1,添加右结点
            else
            {
                f = 0;
                t -> right = new TreeNode(preorder[i]);
                t = t -> right;
                st.push(t);
                i++;
            }
        }
    }

    return root;
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值