思路:
与已知前序遍历的区别在于后序序列要从后向前的顺序建立。
因为前序遍历根节点在其所有子树的前面,而后序遍历的根节点在其所有字数的后面。关键在每次读取两个数组的范围问题:
1) in的边界比较好确定:
有左子树时为[start2,i-1];
有右子树时为[i+1,end2]
2) aft的边界要根据in确定:
有左子树时根据aft和i求出左子树节点个数为:i-start2。所以pre的边界就要包括跳过前(end2-i)个右子树节点, 即:从start1到end1-1-(end2-i)此时综合in的边界为[start1,end1-1-(end2-i),start2,i-1];
有右子树时也要根据aft和i求出左子树节点个数:i-start2。pre的边界就包括前(end2-i)个节点, 即:从end1-(end2-i)到end1-1,此时综合in的边界为[end1-(end2-i),end1-1,i+1,end2]。
总之:在左子树时一定要跨过前面属于右子树的节点,即使没有右子树(此时end2-i等于0)。
代码如下:
aft为后续遍历数组,in为中序遍历数组,start和end为每次递归两个数组的起始与终止下标
BinaryTreeNode* ReBuild(int* aft,int*in,int start1,int end1,int start2,int end2)
{
if((end1-start1)==0)
assert (aft[start1]==in[start2]);
if(end2<start2)
return NULL;
BinaryTreeNode* Temp_Node=new BinaryTreeNode();
Temp_Node->m_nValue=aft[end1];
Temp_Node->m_pLeft=NULL;
Temp_Node->m_pRight=NULL;
for(int i=start2;i<=end2 && in[i]!=aft[end1];i++)
;
assert(i<=end2);
if (i>start2)
Temp_Node->m_pLeft=ReBuild(aft,in,start1,end1-1-(end2-i),start2,i-1);
if(i<end2)
Temp_Node->m_pRight=ReBuild(aft,in,end1-(end2-i),end1-1,i+1,end2);
return Temp_Node;
}