剑指offer--面试题6

题目:由前序、中序遍历序列重建二叉树

虽然思路能想到,但是实际写却无从下手。。。
下面重现作者代码,多多实践。。。

#include<exception>

//首先定义二叉树节点
struct BinaryTreeNode
{
    int bt_Value;
    BinaryTreeNode* bt_pLeft;
    BinaryTreeNode* bt_pRight;
};

//核心函数:ConstructCore(int* StartPreOrder, int* EndPreOrder, int* StartInOrder, int* EndInOrder);
BinaryTreeNode* ConstructCore(int* StartPreOrder, int* EndPreOrder, 
                              int* StartInOrder, int* EndInOrder)
//StartPreOrder,EndPreOrder为先序遍历序列的首尾;StartInOrder,EndInOrder为中序遍历序列的首尾
//总体思路:1、先序遍历首元素即为根节点,创建根节点;
//            2、中序遍历中寻找根节点,以此为界,前面为左子树,后面为右子树;
//            3、函数递归以创建左子树和右子树;
//            递归终止条件:StartPreOrder == EndPreOrder时,StartInOrder同时应等于EndInOrder,为叶子节点。

//因Construct函数中已验证了各个指针项的合法性,所以ConstructCore不再验证。
{
    //根据前序序列首元素创建根节点
    int RootValue = StartPreOrder[0];
    BinaryTreeNode* root = new BinaryTreeNode;
    root->bt_Value = RootValue;
    root->bt_pLeft = root->bt_pRight = NULL;

    //递归终止条件
    if(StartPreOrder == EndPreOrder)
    {
        if(StartInOrder == EndInOrder && *StartPreOrder == *StartInOrder)
            return root;  //该节点为叶子节点,创建子树结束
        else
            throw std::exception("Invalid Input!");
    }

    //在中序序列中寻找根节点位置
    int* rootInOrder = StartInOrder;
    while(rootInOrder <= EndInOrder && *rootInOrder != RootValue)
        rootInOrder++;
    if(rootInOrder > EndInOrder)
        throw std::exception("Invalid Input!");
    //确定左子树的节点个数
    int LeftTreeLength = rootInOrder - StartInOrder;
    int* LeftTreePreOrderEnd = StartPreOrder + LeftTreeLength;
    //创建左子树
    if(LeftTreeLength > 0 )
        root->bt_pLeft = ConstructCore(StartPreOrder+1,LeftTreePreOrderEnd,StartInOrder,rootInOrder-1);
    //创建右子树
    if(rootInOrder < EndInOrder)
        root->bt_pRight = ConstructCore(LeftTreePreOrderEnd+1,EndPreOrder,rootInOrder+1,EndInOrder);
    
    return root;
}

//调用该递归函数的Construct函数如下:
BinaryTreeNode* Construct(int* PreOrder, int* InOrder, int length)
{
    if(PreOrder == NULL || InOrder == NULL || length <= 0)
        return NULL;
    return ConstructCore(PreOrder,PreOrder+length-1,InOrder,InOrder+length-1);
}
//BinaryTree.cpp中的各个接口实现
//1. 创建二叉树节点
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
    BinaryTreeNode* pNode = new BinaryTreeNode;
    pNode->bt_Value = value;
    pNode->bt_pLeft = pNode->bt_pRight = NULL;

    return pNode;
}

//2. 连接树节点
void ConnectBinaryTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
    if(pParent != NULL)
    {
        pParent->bt_pLeft = pLeft;
        pParent->bt_pRight = pRight;
    }
    else
        return;
}

//3. 打印树节点及其孩子节点
void PrintTreeNode(BinaryTreeNode* pNode)
{
    if(pNode != NULL)
    {
        cout<<"The value of this node is: "<<pNode->bt_Value
            <<endl;
        if(pNode->bt_pLeft != NULL)
            cout<<"The value of the left-child node is: "<<pNode->bt_pLeft->bt_Value
                <<endl;
        else
            cout<<"The left-child node is NULL!"<<endl;
        if(pNode->bt_pRight != NULL)
            cout<<"The value of the right-child node is: "<<pNode->bt_pRight->bt_Value
                <<endl;
        else
            cout<<"The right-child node is NULL!"<<endl;
    }
    else
        cout<<"This node is NULL!"<<endl;
}

//4. 打印树 (逐三角打印)
void PrintTree(BinaryTreeNode* pRoot)
{
    PrintTreeNode(pRoot);

    if(pRoot != NULL)
    {
        if(pRoot->bt_pLeft != NULL)
            PrintTree(pRoot->bt_pLeft);
        if(pRoot->bt_pRight != NULL)
            PrintTree(pRoot->bt_pRight);
    }

}

//5. 销毁树
void DestroyTree(BinaryTreeNode* pRoot)
{
    if(pRoot != NULL)
    {
        BinaryTreeNode* pLeft = pRoot->bt_pLeft;
        BinaryTreeNode* pRight = pRoot->bt_pRight;

        delete pRoot;
        pRoot = NULL;

        DestroyTree(pLeft);
        DestroyTree(pRight);
    }
}
清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
原文地址:https://www.cnblogs.com/hello-yz/p/3243710.html