已知二叉树的中序和前序序列(或后序)求解树

在学算法结构时,发现了这个问题,虽然在上数据结构时老师讲过,但是只讲过具体例子,没有让我们训练代码,借这次机会,上网查找了相关资料,而且这学期又刚好在学C++,感觉真的可以好好学一下。。。在网上找的资料,贴在这里和大家共享

 

这种题一般有二种形式,共同点是都已知中序序列。如果没有中序序列,是无法唯一确定一棵树的,证明略。

一、已知二叉树的前序序列和中序序列,求解树。

1、确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素。

2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。

3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。

二、已知二叉树的后序序列和中序序列,求解树。

1、确定树的根。树根是当前树中所有元素在后序遍历中最后出现的元素。

2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。

3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。

举例说明:根据已知求解二叉树

中序序列 HLDBEKAFCG
后序序列 LHDKEBFGCA

1、在后序序列LHDKEBFGCA中最后出现的元素为A,HLDBEK|A|FCG
2、在后序序列LHDKEB中最后出现的元素为B,HLD|B|EK|A|FCG
3、在后序序列LHD中最后出现的元素为D,HL|D|B|EK|A|FCG
4、在后序序列LH中最后出现的元素为H,H|L|D|B|EK|A|FCG
5、在后序序列KE中最后出现的元素为E,H|L|D|B|E|K|A|FCG

5、在后序序列FGC中最后出现的元素为C,H|L|D|B|E|K|A|F|C|G
6、所有元素都已经定位,二叉树求解完成。

                 A
              /     /
             B       C
            / /     /  /
           D  E     F   G
          /    /
         H      K                    
          /                         
           L                     
代码如下:
  1  /*
  2      功能: 1.利用树的前序和中序序列创建树
  3            2.利用树的后序和中序序列创建树
  4  */
  5  #include  < iostream >
  6  #include  < cstring >
  7  using   namespace  std;
  8 
  9  char  pre[ 50 =   " ABDHLEKCFG " ;         // 前序序列
 10  char  mid[ 50 =   " HLDBEKAFCG " ;         // 中序序列
 11  char  post[ 50 =   " LHDKEBFGCA " ;         // 后序序列
 12 
 13  typedef  struct  _Node
 14  {
 15       char  v;
 16       struct  _Node  * left;
 17       struct  _Node  * right;
 18  }Node,  * PNode;
 19 
 20  void  PostTravelTree(PNode pn);         // 树的后序递归遍历
 21  void  PreTravelTree(PNode pn);         // 树的前序递归遍历
 22  void  PreMidCreateTree(PNode  & pn,  int  i,  int  j,  int  len);         // 利用前序中序序列创建树
 23  void  PostMidCreateTree(PNode  & pn,  int  i,  int  j,  int  len);         // 利用后序中序序列创建树
 24  int  Position( char  c);                 // 确定c在中序序列mid中的下标,假设树的各个节点的值各不相同
 25 
 26 
 27  int  main() 
 28 
 29      PNode root1  =  NULL, root2 =  NULL;
 30 
 31      PreMidCreateTree(root1,  0 0 , strlen(mid));
 34      PostTravelTree(root1); cout << endl;    
 36      PostMidCreateTree(root2, strlen(post) - 1 0 , strlen(mid));
 37      PreTravelTree(root2); cout << endl;    
 38 
 39       return   0 ;
 40  }
 41 
 42 
 43  int  Position( char  c)
 44  {
 45       return  strchr(mid,c) - mid;
 46  }
 47 
 48 
 49  /*   利用前序中序序列创建树,参考了http://hi.baidu.com/sulipol/blog/item/f01a20011dcce31a738b6524.html
 50   *的实现,代码十分简洁,竟然只有短短的"令人发指"的8行,递归实在太彪悍了!!!!!!!!!!!!!!!!!!!!!
 51   *        i: 子树的前序序列字符串的首字符在pre[]中的下标
 52   *        j: 子树的中序序列字符串的首字符在mid[]中的下标
 53   *      len: 子树的字符串序列的长度
 54    */
 55  void  PreMidCreateTree(PNode  & pn,  int  i,  int  j,  int  len)
 56  {
 57       if (len  <=   0 )
 58         {   
                  pn = NULL;                 //  这部分原资料里出了点小问题,原资料里没有这一句,结果我在试的时候出了问题
                  return;
              }
 59           
 60      pn  =   new  Node;
 61      pn -> =  pre[i];
 62       int  m  =  Position(pre[i]);
 63      PreMidCreateTree(pn -> left, i + 1 , j, m - j);             // m-j为左子树字符串长度
 64      PreMidCreateTree(pn -> right, i + (m - j) + 1 , m + 1 , len - 1 - (m - j));     // len-1-(m-j)为右子树字符串长度
 65  }
 66 
 67 
 68  /*   利用后序中序序列创建树
 69   *        i: 子树的后序序列字符串的尾字符在post[]中的下标
 70   *        j: 子树的中序序列字符串的首字符在mid[]中的下标
 71   *      len: 子树的字符串序列的长度
 72    */
 73  void  PostMidCreateTree(PNode  & pn,  int  i,  int  j,  int  len)
 74  {
 75       if (len  <=   0 )
          {
               pn = NULL;
 76           return ;
          }
 77 
 78      pn  =   new  Node;
 79      pn -> =  post[i];
 80       int  m  =  Position(post[i]);
 81      PostMidCreateTree(pn -> left, i - 1 - (len - 1 - (m - j)), j, m - j); // 注意参数:m-j左子树的长度,len-1-(m-j)右子树的长度
 82      PostMidCreateTree(pn -> right, i - 1 , m + 1 , len - 1 - (m - j));
 83  }
 84 
 85 
 86  void  PostTravelTree(PNode pn)         // 后序递归遍历
 87  {
 88       if (pn)
 89      {
 90          PostTravelTree(pn -> left);    
 91          PostTravelTree(pn -> right);
 92          cout << pn -> v << "   " ;
 93      }
 94  }
 95 
 96 
 97  void  PreTravelTree(PNode pn)         // 前序递归遍历
 98  {
 99       if (pn)
100      {
101          cout << pn -> v << "   " ;
102          PreTravelTree(pn -> left);    
103          PreTravelTree(pn -> right);
104      }
105 

参考网站  http://www.cnblogs.com/bmrs/archive/2010/08/19/slovetree.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值