编程之美-3.9-重建二叉树

1. 简述

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

struct  NODE {
  NODE
*  pLeft;
  NODE
*  pRight;
  
char  chValue;
};

    假设已经有了前序遍历和中序遍历结果,希望通过一个算法重建这棵树。
    给定函数的定义如下:

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

    参数
    pPreOrder:前序遍历结果的字符串数组。
    pInOrder: 中序遍历结果的字符串数组。
    nTreeLen: 树的长度。
    pRoot:     根据前序和中序遍历结果重新构建树的根节点。
    例如
    前序遍历结果:a b d c e f
    中序遍历结果:d b a e c f

2. 思路

    递归解决相对容易些。
    递归结束条件是长度小于1,此时令*pRoot=NULL即可。
    递归主体中,在中序遍历结果中找前序结果的第一个字符,找到后记录其下标为index,如果找不到说明前序遍历和中序遍历有问题,说明错误信息,然后直接返回。找到index后,新建一个节点,让*pRoot指向它,其数值为前序的第一个字符,然后递归求*pRoot的左孩子和右孩子。
    递归左孩子:Rebuild( pPreOrder+1,pInOrder, index, &((*pRoot)->pLeft) )
    递归右孩子:Rebuild( pPreOrder+index+1, pInOrder+index+1, nTreeLen-index-1, &((*pRoot)->pRight) )

3. 代码   

#include  < iostream >
#include 
< stack >
using   namespace  std;

struct  NODE {
  NODE
*  pLeft;
  NODE
*  pRight;
  
char  chValue;
};

void  Rebuild( char *  pPreOrder,  char *  pInOrder,  int  nTreeLen, NODE **  pRoot) {
  
if (nTreeLen  <=   0 ) {  //  递归结束 
     * pRoot  =  NULL;
    
return ;
  }
  
else  {  //  递归主体 
     int  index  =   0 ;
    
while (index  <  nTreeLen  &&  pPreOrder[ 0 ] != pInOrder[index])
      index
++ ;
    
if (index >= nTreeLen) {
      cout 
<<   " 前序和中序字符串不匹配,有问题 "   <<  endl;
      cout 
<<   " 在中序字符串中,找不到: "   <<  pPreOrder[ 0 <<  endl;
      
return ;
    }
    
else  {
      
* pRoot  =   new  NODE;
      (
* pRoot) -> chValue  =  pPreOrder[ 0 ];
      Rebuild(pPreOrder
+ 1 , pInOrder, index,  & (( * pRoot) -> pLeft));
      Rebuild(pPreOrder
+ index + 1 , pInOrder + index + 1 , nTreeLen - index - 1 & (( * pRoot) -> pRight) );
    }
  }  
}

void  PrintTree( const  NODE *  root) {  //  先根序遍历 
  stack < const  NODE *>  store;
  store.push(root);
  
while ( ! store.empty()) {
    
//  output root
    cout  <<  store.top() -> chValue  <<   " :\t " ;
    
//  output left
     if (store.top() -> pLeft  ==  NULL)
      cout 
<<   " NULL " ;
    
else
      cout 
<<  store.top() -> pLeft -> chValue;
    cout 
<<   "  ,  " ;
    
//  output right
     if (store.top() -> pRight  ==  NULL)
      cout 
<<   " NULL " ;
    
else
      cout 
<<  store.top() -> pRight -> chValue;
    cout 
<<  endl;
    
//  push right
     const  NODE *  tmp  =  store.top();
    store.pop();
    
if (tmp -> pRight)
      store.push(tmp
-> pRight);
    
if (tmp -> pLeft)
      store.push(tmp
-> pLeft);
  }
}
int  main() {
  
char *  pPreOrder  =   " abdcef " ;
  
char *  pInOrder  =   " dbaecf " ;
  NODE
*  pRoot;
  Rebuild(pPreOrder, pInOrder, strlen(pPreOrder), 
& pRoot);
  PrintTree(pRoot);
  system(
" PAUSE " );
  
return   0 ;
}

    输出结果为:
   

4. 参考

    编程之美,3.9节,重建二叉树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值