为什么后序遍历+栈可以找到n到其祖先m的路径?
首先后序遍历的顺序是 左子树->右子树->根节点,了解以下两点是基础①在一个节点的左右子树被访问完之前,该节点始终要保留在栈中②当访问一个节点的右子树时,其左子树全部节点都已经出栈。
正式开始,首先我们从下向上来看,在访问n时,n节点的父亲h,此时一定在栈中,因为n是其子树,h子树当前没有被访问完。同样的,h的父节点e(n的爷爷节点)此时肯定在栈中,因为其有h所在的子树没有遍历完,以此类推,可知n节点的所有祖先节点都在栈中。
那栈中有没有多余的节点呢?没有,N到根节点路径右边的节点此时还没有入栈(广义上的右),而路径左边的节点,如图中DFG节点(只要所寻路径不是整个子树的最左侧路径就一定存在位于路径左边的节点),其到根节点的路径与所寻路经一定有一部分公共路径(图中A-B),并且有一个关键的共同子树根节点(图中的B),而N所在的为该节点B的右子树,当访问到B的右子树的时候,该节点的左子树所有节点(DFG)此时已经出栈(从代码执行可知),所以综上所述,n到根节点路径左边和右边的所有节点都不在栈中,即栈中无多余元素。
综合以上两点,当访问到所寻的节点N时,当前栈中所存储的就是N节点到根节点的全部祖先节点,且按顺序。如果要找到N到指定祖先M的路径,只需要将栈中元素依次出栈,直到M出栈后停止,所组成的序列即为所求路径。
后序遍历代码如下:
void BeOrder(BiTree p){
InitStack(S);
BiTree p = null, r = null;
while(p!=null||isEmpty(S)){
if(p!=null){
Push(S,p);
p = p->lchild;
}
else{
GetTop(S,p);
if(p->rchild!=null||p->rchild!=r){
p = p->rchild;
}
else{
Pop(S,p);
visit(p);
r = p;
p = null;
}
}
}
}