【剑指offer】第六题-重建二叉树

6 篇文章 1 订阅
2 篇文章 0 订阅

问题描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出其头节点。
问题分析:
在二叉树前序遍历中,第一个数字总是树的根节点的值。但在中序遍历中根节点则在中间,且左子树的节点的值在根节点的左边,右子树的节点的值在根节点的右边。如下图所示:
这里写图片描述
根据二叉树前序遍历和中序遍历的过程,我们可以:
1、先从前序遍历序列中找第一个节点构造根节点;
2、从中序遍历序列中找到根节点,则根节点左边的数据就是该根节点左子树的节点的值,根节点右边的数据就是该根节点右子树的节点的值;
3、求出左子树的长度,递归的构建左子树;
4、从根节点后一个节点开始来构建右子树。
代码实现如下:

#include<iostream>
using namespace std;
struct BinaryTreeNode
{
    int value;
    BinaryTreeNode * left;
    BinaryTreeNode * right;
    BinaryTreeNode(int v=int())
        :value(v)
        ,left(NULL)
        ,right(NULL)
    {}
};
class ReBulidBinaryTree
{
public:
    typedef BinaryTreeNode Node;
    Node * ReBulid(int *PrevStart, int * PrevEnd, int * InStart, int *InEnd)
    {
        Node * root = new Node(PrevStart[0]);
        root->left = root->right = NULL;
        if (PrevStart == PrevEnd && InStart == InEnd)
        {
            return root;
        }
        //中序遍历序列中找根节点
        int * rootInorder = InStart;
        while (rootInorder <=InEnd && *rootInorder != PrevStart[0])
        {
            rootInorder++;
        }
        if (rootInorder > InEnd)//没有找到根节点
        {
            cout<<"input error"<<endl;
            return NULL;
        }
        int LeftLen = rootInorder - InStart;
        if (LeftLen > 0)
        {
            root->left = ReBulid(PrevStart + 1, PrevStart + LeftLen, InStart, rootInorder - 1);
        }
        if (rootInorder < InEnd)
        {
            root->right = ReBulid(PrevStart + LeftLen + 1, PrevEnd, rootInorder + 1, InEnd);
        }
        return root;
    }
    Node * ReBulidTree(int* PrevOrder, int *InOrder, int len)
    {
        if (PrevOrder == NULL || InOrder == NULL || len <= 0)
        {
            return NULL;
        }
        _root= ReBulid(PrevOrder, PrevOrder + len - 1, InOrder, InOrder + len - 1);
    }
    void PostOrder()//后序遍历二叉树
    {
        PostOrder(_root);
    }
    void PostOrder(Node *root)//后序遍历二叉树
    {
        if (root)
        {
            PostOrder(root->left);
            PostOrder(root->right);
            cout << root->value << " ";
        }
    }
private:
    Node * _root;
};


int main()
{
    int PrevOrder[] = { 1,2,4,7,3,5,6,8 };
    int InOrder[] = { 4,7,2,1,5,3,8,6 };
    int PrevLen = sizeof(PrevOrder) / sizeof(PrevOrder[0]);
    int InLen = sizeof(InOrder) / sizeof(InOrder[0]);
    if (PrevLen != InLen)
    {
        cout << "input error!" << endl;
        return -1;
    }
    ReBulidBinaryTree rb;
    rb.ReBulidTree(PrevOrder, InOrder, PrevLen);
    rb.PostOrder();
    cout << endl;
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值