剑指offer之重建二叉树

来源:互联网 发布:mac 进入屏保 编辑:程序博客网 时间:2024/04/29 09:03

题目: 

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。例如,前序遍历序列:{1,2,3,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6},请重建出如图所示的二叉树。


分析:

    如图所示,前序遍历序列的第一个数字1就是跟结点的值。扫描中序遍历序列,就能确定跟结点的值的位置。根据中序遍历特点,在根结点的值1前面的3个数字都是左子树结点的值,为于1后面的数字都是右子树的值。在中序遍历中,有3个数字是左子树的值,因此左子树总共有3个左子结点。同样,在前序遍历中,根结点后面的3个数字就是3个左子树节点的值,同后面的所有数字都是右子树节点的值。既然分别找到了左右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法去构建左右字树。用递归的方法。


代码:

struct BinaryTreeNode 

{

     int  m_nValue ;

    BinaryTreeNode  * m_pLeft;

    BinaryTreeNode  * m_pRight;

}

     

BinaryTreeNode * constuct(int* preorder, int* inorder, int length){    if(preorder == NULL || inorder == NULL || length <= 0)    {        return NULL;    }    return construct_method(preorder, preorder+length-1, inorder,inorder+length-1);}
BinaryTreeNode * construct_method(int* preorder, int* endpreorder, int* inorder, int* endinorder)
{ int root_value = preorder[0];
         BinaryTreeNode * root = new BinaryTreeNode();
    root->m_nValue = root_value ;
root->left = NULL; root->right = NULL;
    if(preorder == endpreorder) { //如果只有一个结点,则返回该结点的指针。
        if(inorder == endinorder && *preorder == *endpreorder)
            return root;
        else
            throw std::exception("Invalid input.");    }    
//在中序遍历中查找根结点的值    int* rootInorder = inorder;    while(*rootInorder != root_value && rootInorder < endinorder)        rootInorder++;    int left_len = rootInorder - inorder;    int* left_preorder_end = preorder + left_len;    //构建左子树    if(left_len > 0)    {        root->m_pLeft = construct_method(preorder+1, left_preorder_end, inorder, rootInorder-1);    }    //构建右子树    if(left_len < endpreorder - preorder)    {        root->m_pRight = construct_method(left_preorder_end+1, endpreorder, rootInorder+1, endinorder);    }    return root;}
//测试
int main(){    int pre[8] = {1,2,4,7,3,5,6,8};    int in[8]  = {4,7,2,1,5,3,8,6};    binary_tree_node* root = binary_tree_constuct(pre, in, 8);}


0 0