Sicily 1210 二叉树 (Binary tree)

本文探讨了由二叉树的前序和后序遍历序列确定不同形态二叉树数量的问题。阐述了仅凭这两种遍历无法唯一确定二叉树形态的原因,并提供了一种计算所有可能形态数量的方法。

题目的大意是,给出一颗二叉树的前序和后序遍历,求符合遍历的不同形态的二叉树的数目。

 

为什么已知一棵二叉树的前序和后序遍历,不一定能重建唯一的二叉树呢?原因在于,当一个根只有一颗子树时,通过前序遍历和后序遍历,无法确定该子树是这个根的左子树还是右子树。如下图所示两颗树,前序遍历均为ab,后序遍历均为ba。

 

观察上面的两棵树,我们可以发现如下规律:当一个根(a)只有一棵子树时,前序遍历在该单子树的根(b)的前一个元素(a)必然与后序遍历在该单子树的根(b)的后一个元素(a)相同。

 

另外,单子树既可以是左子树,也可以是右子树,因此总的可能情况应该是2 的单子树个数次方。

 

综上,解题思路可以如下:先求出单子树的个数,最终结果为 2 的单子树个数次方。

Other Tips:

1:前序遍历第一个元素是根,后序遍历最后一个元素是根  

2:前序遍历第二个元素是某子树的根,但左右不确定  

3:在后序遍历中找到前序遍历的第二个元素,那么以这个元素为基准,可以划分新的左右子树  

4:当前序遍历的第二个元素出现在后序遍历的倒数第二位,以后序遍历倒数第三位起向左数都是子树的元素,但是左右不确定,因此有2种情况  

5:可使用递归或非递归方法实现。

 

1 /************************************************************************/
2  /* Sicily 1210 Binary Tree. Plutoyang.2010-12-15 */
3  /************************************************************************/
4 #include <stdio.h>
5 #include <string.h>
6
7  #define MAXLEN 10000
8
9  //traverse list
10  typedef struct
11 {
12 int root; //root of a subtree
13   char order[MAXLEN]; //traverse sequence
14 }traList;
15
16 traList pre, post; //define pre-order list and post-order list
17
18 int main()
19 {
20 int len, cnt = 1;
21
22 scanf("%s%s",&pre.order, &post.order); //read in pre-order list and post-order list
23 len = strlen(pre.order); //calculate the number of the node
24
25 if(len == 1) //special case: a tree with only one node
26 {
27 printf("%d",cnt);
28 return 0;
29 }
30
31 for(pre.root = 1; pre.root < len; pre.root++) //for each subroot in preoder list
32 { //find this subroot in post-order list
33 post.root = len - 2;
34 while(pre.order[pre.root] != post.order[post.root])
35 {
36 post.root --;
37 }
38
39 /* 一开始是这样,然后就错了
40 if(pre.order[pre.root + 1] == post.order[post.root - 1])
41 */
42 //now val[pre.root] == val[post.root], test whether the tree is a single tree or binary tree
43 if(pre.order[pre.root - 1] == post.order[post.root + 1])
44 cnt *= 2;
45 }
46
47 printf("%d", cnt);
48 return 0;
49 }

转载于:https://www.cnblogs.com/platero/archive/2010/12/16/1907548.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值