已知中序和前序(或后序)遍历结果生成树

时间:2021-07-27 12:36:10

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

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

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 
  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 
 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 
 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