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

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

(解释部分来自http://www.slyar.com/blog/ )

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

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

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            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 )
 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   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值