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 }