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 }