题目大意:
根据一颗树的中序遍历和前序遍历求出这棵树的后序遍历。
样例输入:
ABEDFCHG
CBADEFGH
样例输出:
AEFDBHGC
这道题我先讲一下自己的建树方法:
我们知道一颗树的中序遍历,前序遍历,后序遍历的顺序是这样子的:
左根右
根左右
左右根
所以我们可以根据前序遍历找出当前这颗树的根。例如样例中,这颗树的根是C,则这颗树的左右子树分别为——ABEDF,HG——这是根据中序遍历得出来的结果,然后我们可以再根据前序遍历的第2个字母得出左子树的根为B,然后这颗树的左右子树分别为——A,EDF。以此类推——最后我们可以得到如下的一棵树——从这里我们就可以得出后序遍历为AEFDBHHC了。
具体解释在代码里解释:
var s1,s2:string; len,k,x:longint; a:array['A'..'Z',1..2] of char; procedure dfs(s:string; t:longint); var w:longint; begin inc(k);<span style="white-space:pre"> </span>//这里是数当前分了几段了,k等于多少的时候就是 w:=pos(s2[k],s);<span style="white-space:pre"> </span>//这里是找当前需要分解的s子串的根节点在哪里,方便往子串的两端分解。 if length(copy(s,1,w-1))>0 then<span style="white-space:pre"> </span>//如果左边可以分解,则往左边分 begin a[s1[t],1]:=s2[k+1];<span style="white-space:pre"> </span>//t表示当前分解到s1串的哪个位置,s2[k+1]就是下次分解的根节点,也是需要记录的节点。 dfs(copy(s,1,w-1),pos(s2[k+1],s1));<span style="white-space:pre"> </span>//这里的t更新为这个数是方便下次记录。 end; if length(copy(s,w+1,length(s)-w))>0 then begin a[s1[t],2]:=s2[k+1]; dfs(copy(s,w+1,length(s)-w),pos(s2[k+1],s1)); end; end; procedure print(ch:char);<span style="white-space:pre"> </span>//后序遍历输出 begin if a[ch,1] in ['A'..'Z'] then begin print(a[ch,1]); write(a[ch,1]); end; if a[ch,2] in ['A'..'Z'] then begin print(a[ch,2]); write(a[ch,2]); end; end; begin readln(s1); readln(s2); len:=length(s1); dfs(s1,pos(s2[1],s1)); print(s2[1]); writeln(s2[1]); end.
当然还有另一种方法,也就是在构树的时候直接输出后序遍历:
var s1,s2:string; procedure dfs(x,y:string); var w:longint; begin if length(x)<=1 then write(x[1])<span style="white-space:pre"> </span>//这里是输出“左右” else begin w:=pos(x[1],y);<span style="white-space:pre"> </span>//查找当前子串的根节点 dfs(copy(x,2,w-1),copy(y,1,w-1));<span style="white-space:pre"> </span>//往根节点的两边分。 dfs(copy(x,w+1,length(x)-w),copy(y,w+1,length(y)-w)); write(x[1]);<span style="white-space:pre"> </span>//这里是输出“根” end; end; begin readln(s1); readln(s2); dfs(s2,s1); end.