POJ 2255 -- Tree Recovery

Tree Recovery
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16032   Accepted: 9865

题意:

根据二叉树的先序遍历和中序遍历,求后序遍历。

解题思路:

1)递归(不建树)

可以先按照用笔和纸的形式去推导出后序序列。推导过程省略,在推导过程中我们会发现规律:

假设 前序序列是 A B E H F C G I

 中序序列是 H E B F A C I G (图如下)

 

每一次从前序序列里,按顺序抽取出字母就能将中序序列分割,并根据中序遍历的特性。分割后的两部分分别是 左子树 和 右子树(注意,他们也是二叉树!)

就像这样:取A, 中序序列被分割为 左子树:H E B F  右子树 C I G

继续取B,但是这次是对左子树:H E B F 进行分割。 分割结果是: 左子树:H E  右子树  B F

直到不能再分割,递归会返回去到第一次使用 A 分割出来的 右子树 里继续分割

上述整个过程都是递归,所以结合代码和用纸笔画一次会更好理解

char *strchr(const char* _Str,char _Val)
头文件:#include <string.h>
功能:查找字符串_Str中首次出现字符_Val的位置
说明:返回首次出现_Val的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL
返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL
 
 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn = 30;
 5 
 6 
 7 void Build(char *a,char *b,char *s,int n)
 8 {//a是先序遍历,b是中序遍历
 9     if(n<=0)
10         return;
11     else{
12         ///记录根节点在中序遍历中的位置
13         int k = strchr(b,a[0]) - b;
14         ///0~k-1为左子树
15         Build(a+1,b,s,k);
16         ///k+1~n为右子树
17         Build(a+k+1,b+k+1,s+k,n-k-1);
18         s[n-1] = a[0];
19     }
20 }
21 
22 int main()
23 {
24     char a[maxn],b[maxn];
25     while(cin>>a>>b)
26     {
27         char ans[maxn];
28         int len = strlen(b);
29         Build(a,b,ans,len);
30         ans[len] = 0;///加结束符
31         cout<<ans<<endl;
32     }
33     return 0;
34 }

 

 2)二叉树遍历(建树)

对二叉树的 前序遍历、中序遍历、后序遍历 均可以使用DFS来做,
均是自上而下、自左至右遍历,区别在于打印节点的时机不同:
[前序遍历] 从父节点进入时打印当前节点
[中序遍历] 从左子树返回时打印当前节点
[后序遍历] 从右子树返回时打印当前节点

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 
 5 using namespace std;
 6 const int STR_LEN = 27;//树遍历序列最大长度
 7 const int NULL_CHAR = '\0';//空字符
 8 
 9 ///结点结构
10 class Node{
11 public:
12     char name;//节点名称
13     Node *left;//左子树根节点
14     Node *right;//右子树根节点
15     Node():name(NULL_CHAR),left(NULL),right(NULL){}//初始化
16     ~Node()
17     {
18         name = NULL_CHAR;
19         delete left;left = NULL;
20         delete right;right = NULL;
21     }
22 };
23 
24 Node* createTree(char *pro,char *in,int n)
25 {
26     Node *root = new Node;
27     if(n <= 0)
28     {
29         return root;
30     }else{
31         int k = strchr(in,pro[0]) - in;//找到根节点在中序遍历中的位置
32         root->name = pro[0];
33         root->left = createTree(pro+1,in,k);
34         root->right = createTree(pro+k+1,in+k+1,n-k-1);
35         return root;
36     }
37 }
38 
39 void dfs(Node *root,char *output)
40 {
41     if(root == NULL)
42     {
43         return;
44     }
45     dfs(root->left,output);
46     dfs(root->right,output);
47     ///构造后序序列,从右子树返回时把当前的结点放到序列末尾
48     output[strlen(output)] = root->name;
49     //或写成:
50     //*(output+strlen(output)) = root->name;
51 }
52 
53 int main()
54 {
55     char pro[STR_LEN],in[STR_LEN];
56     while(cin>>pro>>in)
57     {
58         int len = strlen(in);
59         Node *root = createTree(pro,in,len);
60         char output[STR_LEN] = {NULL_CHAR};///一定要初始化为空
61         dfs(root,output);
62         output[len] = 0;
63         cout<<output<<endl;
64         delete root;
65     }
66     return 0;
67 }

 


posted @ 2018-02-13 23:00  卉卉卉大爷  阅读(121)  评论(0编辑  收藏  举报