对于一棵树的中序遍历,根节点肯定处于遍历结果的中间(假设这棵树有左子树),后序遍历的时候根节点肯定是最后一个遍历的元素。所以可以轻易得到根在中序遍历中的位置,根据中序遍历的性质,以根为中点往后遍历到的元素就是这棵树的右子树元素,往前遍历到的就是这棵树的左子树元素。而后续遍历也是把这棵树的左子树全部遍历完整之后再来遍历右子树,因此在后续遍历中,左子树和右子树的元素也是有明显的界限。而对于根节点的左节点和右节点也是同样的道理。举个例子
于是我们记录 [start,ending] -> 根结点在中序遍历中的掌控范围,pos - > 根结点在后续遍历的位置
#include<bits/stdc++.h>
using namespace std;
int mid[15] = {0,4,3,2,5,1,7,8,6};
int last[15] = {0,4,3,5,2,8,7,6,1};
vector<int> G[15];
///pos是指在last中的位置,fa是last[pos]的父亲结点,start,ending是last[pos]为根所在的子树所包括的所有结点.
void solve(int pos,int fa,int start,int ending)
{
if(start > ending) return ;
G[fa].push_back(last[pos]); ///建边
int i=start;
while(i<=ending && mid[i]!=last[pos]) i++; /// 这里是找到根结点在中序遍历中的位置
solve(pos-ending+i-1,last[pos],start,i-1); /// 递归左子树
solve(pos-1,last[pos],i+1,ending); /// 递归右子树
}
void print(int pos) {
if(pos != 0) printf("%d\n",pos);
for(int i=0;i<G[pos].size();i++) {
print(G[pos][i]);
}
}
int main()
{
solve(8,0,1,8);
printf("\n");
print(0);
}