第三章 -- 重建二叉树

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

struct NODE

{

NODE *pLeft;

NODE *pRight;

char chValue;

};

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

给定函数的定义如下:

void Rebuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot)

参数:

pPreOrder:以null为结尾的前序遍历结果的字符串数组。

pInOrder:以null为结尾的中序遍历结果的字符串数组。

nTreeLen:树的长度。

pRoot:返回node**类型,根据前序和中序遍历结果重新构建树的根节点。

例如:

前序遍历结果:a b d c e f

中序遍历结果:d b a e c f

重建的树如图:



递归解决问题:

#include <iostream>

#define TREELEN 6

using namespace std;

struct NODE
{
       NODE *lchild;
       NODE *rchild;
       char chValue;
};

void Rebuild(char *pPreOrder, char *pInOrder, int nTreeLen, NODE **pRoot)
{
     if(pPreOrder==NULL || pInOrder==NULL)
         return;
     
     // 获得前序遍历的第一个节点 
     NODE *pTemp=new NODE;
     pTemp->chValue=*pPreOrder;
     pTemp->lchild=NULL;
     pTemp->rchild=NULL;
     
     if(*pRoot==NULL)
         *pRoot=pTemp; 
     
     if(nTreeLen==1)
         return;
         
     // 开始解析字符串
     char *p1=pInOrder;
     char *p2=pInOrder;
     //int len=0;
     
     while(*p1!=*pPreOrder)
         p1++;
     //len=p1-p2;
     
     int leftlen=(int)(p1-p2);   // 左子树长度 
     int rightlen=nTreeLen-leftlen-1;    // 右子树长度                     
     
     // 重建左子树 
     if(leftlen>0)
         //Rebuild(pPreOrder+1, pInOrder, leftlen, &(*pRoot->lchild));   ->优先级大于* 
         Rebuild(pPreOrder+1, pInOrder, leftlen, &((*pRoot)->lchild));  
     // 重建右子树
     if(rightlen>0)
         //Rebuild(pPreOrder+len+1, pInOrder+len+1, rightlen, &(*pRoot->rchild)); 
         Rebuild(pPreOrder+leftlen+1, pInOrder+leftlen+1, rightlen, &((*pRoot)->rchild));
}

int PostOrderTraverse(NODE *root)
{
    if(root==NULL)
        return 0;
    PostOrderTraverse(root->lchild);
    PostOrderTraverse(root->rchild);
    cout<<root->chValue<<endl;
} 

int main()
{
    char szPreOrder[TREELEN]={'a','b','d','c','e','f'};
    char szInOrder[TREELEN]={'d','b','a','e','c','f'};
    
    NODE *pRoot=NULL;
    Rebuild(szPreOrder, szInOrder, TREELEN, &pRoot);
    
    // 后序遍历测试
    PostOrderTraverse(pRoot); 
    
    return 0;
}
 
测试用例结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值