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

(解释部分来自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 

.

    原文作者:AutoDev
    原文地址: https://www.cnblogs.com/bmrs/archive/2010/08/19/SloveTree.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞