编程之美--根据遍历结果重建二叉树

本文探讨如何根据二叉树的前序和中序遍历结果重建二叉树。通过分析遍历定义,我们发现前序遍历的每个节点是其子树的根节点,而中序遍历可以将子树分为左右两部分。利用这些规律,我们可以设计算法来重建二叉树结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      学过数据结构和算法的人都能很快的写出二叉树的三种遍历次序。
     那么如果已经知道了遍历的结果,能不能把一颗二叉树重新构造出来呢?

   给定一颗二叉树,假设每个节点都用唯一的字符来表示,具体结构如下:

struct Node
{
    struct Node* pLeft;
    struct Node* pRight;
    char value;
};


假设已经有了前序和中序遍历结果,希望通过一个算法重建这个二叉树。

分析:先回忆一下前序和中序遍历的定义。

      前序遍历:先访问当前结点,然后以前序遍历顺序访问左子树和右子树。

     中序遍历:以中序遍历顺序访问左子树,接着访问当前节点,然后以中序遍历顺序访问右子树。

根据定义,可以发现如下规律:

前序遍历的每一个节点,都是当前子树的根节点。同时,以对应的结点为边界,就会把中序遍历结果

分为左子树和右子树。

前序:b d c e f     a是根节点

中序:d  b  a e  c  f   a是根节点,把字符串分成左右两个子树

 

实现:

/**/

//定义树的长度
#define TREELEN 6
#include<iostream>
using namespace std;

struct Node
{
    struct Node* pLeft;
    struct Node* pRight;
    char value;
};

void Rebuild(char *pPreOrder,//前序遍历结果
             char *pInorder,//中序遍历结果
             int nTreeLen,//树的长度
             Node **pRoot)//根节点
{
    //检查边界条件
    if(pPreOrder==NULL ||pInorder==NULL)
    {
        return ;
    }
    //获得前序遍历的第一个结点
    Node *pt=new Node ;
    pt->value=*pPreOrder;
    pt->pLeft=NULL;
    pt->pRight=NULL;
    //如果根节点为空,将该节点设置为根节点,首次会调用
    if(*pRoot==NULL)
    {
        *pRoot=pt;
    }
    //如果深度为1,那么已经是叶节点了
    if(nTreeLen==1)
    {
        return;
    }
    //在中序遍历中寻找左子树
    char *pOrgInOrder=pInorder;
    char *pLeftEnd=pInorder;
    int ntemp=0;
    //找到左子树的结尾
    while(*pPreOrder!=*pLeftEnd)
    {
        if(pPreOrder==NULL||pLeftEnd==NULL)
        {
            return;
        }
        ntemp++;
        if(ntemp>nTreeLen)
        {
            return;
        }
        pLeftEnd++;
    }
    //确定左子树的长度
    int nLeftLen=0;
    nLeftLen=(int)(pLeftEnd-pOrgInOrder);
    //确定右子树的长度
    int nRightLen=0;
    nRightLen=nTreeLen-nLeftLen-1;
    
    //重建左子树
    if(nLeftLen>0)
    {
        Rebuild(pPreOrder+1,pInorder,nLeftLen,&((*pRoot)->pLeft));
    }
    //重建右子树
    if(nRightLen>0)
    {
        Rebuild(pPreOrder+nLeftLen+1,pInorder+nLeftLen+1,nRightLen,&((*pRoot)->pRight));
    }
}

int main()
{
    char PreOrder[]={'a','b','d','c','e','f'};
    char InOrder[]={'d','b','a','e','c','f'};
    Node *root=NULL;
    Rebuild(PreOrder,InOrder,TREELEN,&root);
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值