根据先序序列和中序序列重建二叉树

参考资料:《剑指offer》

问题如下:已知二叉树的先序序列和中序序列,编写函数实现该二叉树的重建,假设二叉树中无重复元素。
假设某二叉树:
先序序列:{1,2,4,7,3,5,6,8}
中序序列:{4,7,2,1,5,3,8,6}
思路:二叉树先序遍历的第一个结点就是根节点,中序遍历根节点在中间,左边是左子树的结点,右边是右子树的结点,这样,根据两种遍历就可以确定左子树和右子树结点的先序和中序遍历序列。如1是根节点,中序序列1左边有3个结点(该三个结点也是左子树中序序列),说明先序序列1后面3个结点是左子树的先序遍历结果。通过递归,可完成整棵树的构建。
代码如下:
实现代码:

#define NULL 0
//根据先序序列和中序序列重建二叉树
BinaryTreeNode* ConstructTree(int* preOrder,int* inOrder,int length)
{
    if (NULL==preOrder || NULL==inOrder || length<=0)
        return NULL;

    //重建根节点,先序序列第一个结点
    int rootValue=preOrder[0];
    BinaryTreeNode* rootNode=new BinaryTreeNode;
    rootNode->m_nValve=preOrder[0];

    //在中序序列中寻找根节点,计算左右子树节点数
    int i;
    int leftNodeNum,rightNodeNum;
    for (i=0;i<length;i++)
    {
        if (rootValue==inOrder[i])
        {
            break;
        }
    }
    leftNodeNum=i;
    rightNodeNum=length-1-i;

    //也可以不用判断左右结点数目
    //重建左子树
    if (leftNodeNum>=1)
    {
        rootNode->m_pLeft=ConstructTree(preOrder+1,inOrder,leftNodeNum);
    }
    else
    {
        rootNode->m_pLeft=NULL;
    }
    //重建右子树
    if (rightNodeNum>=1)
    {
        rootNode->m_pRight=ConstructTree(preOrder+leftNodeNum+1,inOrder+leftNodeNum+1,rightNodeNum);
    }
    else
    {
        rootNode->m_pRight=NULL;    
    }

    //返回根节点
    return rootNode;

}

调用代码:

void main()
{
    int length=8;
    int preOrder[]={1,2,4,7,3,5,6,8};
    int inOrder[]={4,7,2,1,5,3,8,6};

    //构建树
    BinaryTreeNode* pTree=ConstructTree(preOrder,inOrder,length);
    //先序输出
    printTreePreOrder(pTree);
    printf("\n");
    //中序输出
    printTreeInOrder(pTree);
    ReleaseTree(&pTree);
}

附其它函数代码:

//输出先序序列
void printTreePreOrder(BinaryTreeNode* pTree)
{
    if (NULL==pTree)
    {
        return;
    }

    printf("%d,",pTree->m_nValve);
    printTreePreOrder(pTree->m_pLeft);
    printTreePreOrder(pTree->m_pRight);
}
//输出中序序列
void printTreeInOrder(BinaryTreeNode* pTree)
{
    if (NULL==pTree)
    {
        return;
    }

    printTreeInOrder(pTree->m_pLeft);
    printf("%d,",pTree->m_nValve);
    printTreeInOrder(pTree->m_pRight);
}
//释放二叉树
void ReleaseTree(BinaryTreeNode** pTree)
{
    if (NULL==(*pTree))
    {
        return;
    }

    ReleaseTree(&((*pTree)->m_pLeft));
    ReleaseTree(&((*pTree)->m_pRight));

    delete (*pTree);
    (*pTree)=NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值