二叉树前序、中序、后序遍历相互求法

 

参考资料:

  [1]:https://blog.csdn.net/m0_37698652/article/details/79218014

 

一、已知前序、中序遍历,求后序遍历

  例:

  前序遍历: GDAFEMHZ

  中序遍历: ADEFGHMZ

  画树求法:

  第一步,根据前序遍历的特点,我们知道根结点为G

  第二步,观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树,G右侧的HMZ必然是root的右子树。

  第三步,观察左子树ADEF,左子树的中的根节点必然是root结点的leftchild。在前序遍历中,root的leftchild紧挨着root之后,所以左子树的根节点为D。

  第四步,同样的道理,root的右子树节点HMZ中的根节点也可以通过前序遍历求得。在前序遍历中,一定是先把root和root的所有左子树节点遍历完之后

  才会遍历右子树,并且遍历的左子树的第一个节点就是左子树的根节点。同理,遍历的右子树的第一个节点就是右子树的根节点。

  第五步,观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。

  最后就可以还原一棵树了。

  那么,我们可以画出这个二叉树的形状:
  

  那么,根据后序的遍历规则,我们可以知道,后序遍历顺序为:AEFDHZMG

代码如下:

 1 /**
 2     假设所有节点由互不相等的大写字母组成;
 3     将字母'A'~'Z'由'0'~'25'表示 
 4 */ 
 5 #include<iostream>
 6 #include<cstdio>
 7 #include<cstring>
 8 using namespace std;
 9 #define ls(x) (x<<1)
10 #define rs(x) (x<<1|1)
11 #define mem(a,b) memset(a,b,sizeof(a))
12 const int maxn=1000;
13 
14 int tree[4*maxn];
15 char preOrder[maxn];//前序遍历 
16 char inOrder[maxn];//中序遍历 
17 int pos[30];//pos[i]:节点i在中序遍历中的位置 
18 
19 void DFS(int l,int r,int curPos,int &k)
20 {
21     if(l > r)
22         return ;
23     tree[curPos]=preOrder[k++]-'A';
24     
25     if(l == r)
26         return ;
27             
28     /**
29         分别递归左右子树
30         根据前序遍历的特点先递归左子树 
31     */ 
32     int mid=pos[tree[curPos]];
33     DFS(l,mid-1,ls(curPos),k);
34     DFS(mid+1,r,rs(curPos),k);
35 }
36 
37 void Print(int index)
38 {
39     if(tree[index] == -1)
40         return ;
41         
42     Print(ls(index));
43     Print(rs(index));
44     printf("%c",'A'+tree[index]);
45 }
46 void Solve()
47 {
48     mem(tree,-1);
49     int len=strlen(preOrder);
50     for(int i=0;i < len;++i)
51         pos[inOrder[i]-'A']=i;
52         
53     tree[1]=preOrder[0]-'A';//根节点 
54     int k=1;
55     int mid=pos[tree[1]];//求出根节点在中序遍历中的位置 
56     DFS(0,mid-1,ls(1),k);//左子树[0,mid-1] 
57     DFS(mid+1,len-1,rs(1),k);//右子树[mid+1,len-1] 
58     
59     Print(1);//输出后序遍历结果 
60 }
61 int main()
62 {
63 //    freopen("C:/Users/hyacinthLJP/Desktop/stdin/contest","r",stdin);
64     while(~scanf("%s%s",preOrder,inOrder))
65         Solve();
66         
67     return 0;
68 }
View Code

 


二、已知中序和后序遍历,求前序遍历

  依然是上面的题,这次我们只给出中序和后序遍历:

  中序遍历: ADEFGHMZ

  后序遍历: AEFDHZMG

  画树求法:
  第一步,根据后序遍历的特点,我们知道后序遍历最后一个结点即为根结点,即根结点为G。

  第二步,观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树,G右侧的HMZ必然是root的右子树。

  第三步,观察右子树HMZ,右子树的中的根节点必然是root的rightChild。在后序遍历中,root的rightChild紧挨着root之前,所以右子树的根节点为M。

  第四部,以此类推,根据后序遍历的特点,紧邻着当前根节点G的前一个节点一定是右子树的根节点,当右子树全部还原后,开始还原左子树;

  那么,前序遍历: GDAFEMHZ

代码如下:

 1 /**
 2     假设所有节点由互不相等的大写字母组成;
 3     将字母'A'~'Z'由'0'~'25'表示 
 4 */ 
 5 #include<iostream>
 6 #include<cstdio>
 7 #include<cstring>
 8 using namespace std;
 9 #define ls(x) (x<<1)
10 #define rs(x) (x<<1|1)
11 #define mem(a,b) memset(a,b,sizeof(a))
12 const int maxn=100;
13 
14 char midOrder[maxn];//中序遍历 
15 char nexOrder[maxn];//后序遍历 
16 int tree[4*maxn];
17 int pos[30];//pos[i]:节点i在中序遍历中的位置 
18 
19 void DFS(int l,int r,int curPos,int &k)
20 {
21     if(l > r)
22         return ;
23 //    printf("l=%d,r=%d\n",l,r);
24     tree[curPos]=nexOrder[k--]-'A';
25     if(l == r)
26         return ;
27         
28     /**
29         分别递归右左子树
30         根据前序遍历的特点先递归右子树 
31     */ 
32     int mid=pos[tree[curPos]];
33     DFS(mid+1,r,rs(curPos),k);
34     DFS(l,mid-1,ls(curPos),k);
35 }
36 void Print(int index)
37 {
38     if(tree[index] == -1)
39         return ;
40         
41     printf("%c",'A'+tree[index]);
42     Print(ls(index));
43     Print(rs(index));
44 }
45 void Solve()
46 {
47     mem(tree,-1);
48     int len=strlen(midOrder);
49     for(int i=0;i < len;++i)
50         pos[midOrder[i]-'A']=i;
51     
52     tree[1]=nexOrder[len-1]-'A';//根节点 
53     int mid=pos[tree[1]];//求出根节点在中序遍历中的位置 
54     int k=len-2;
55     DFS(mid+1,len-1,rs(1),k);//右子树[mid+1,len-1] 
56     DFS(0,mid-1,ls(1),k);//左子树[0,mid-1] 
57     
58     Print(1);//前序遍历 
59     printf("\n");
60 }
61 int main()
62 {
63 //    freopen("C:/Users/hyacinthLJP/Desktop/stdin/contest","r",stdin);
64     while(~scanf("%s%s",midOrder,nexOrder))
65         Solve();
66         
67     return 0;
68 }
View Code

 

posted @ 2019-03-22 20:49  HHHyacinth  阅读(937)  评论(0编辑  收藏  举报