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 = '