您的位置:首页 > 其它

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

2015-01-26 17:01 453 查看
转自 博客园 行有制blog:http://www.cnblogs.com/bmrs/archive/2010/08/19/SloveTree.html

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



.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐