算法思想:使用非递归的后序遍历,假设p在q的左边用栈保存二叉树的指针,栈 S 中全部元素都是当前指针 p 的祖先们。
判断方法:先将栈复制到一个辅助栈 tempS 中,继续遍历到结点 q 的时候,将栈中元素从栈顶开始逐个和辅助栈 tempS 去匹配,第一个相等的元素就是结点p q的公共祖先。
算法实现如下:
typedef struct
{
BiTree T;
int tag; //0表示左孩子被访问过了,1表示左孩子早已被访问,右孩子刚被访问
}
stack s, tempS; //假设栈空间足够大,足以满足二叉树的所有结点数
BiTree Ancestor(BiTree root, BiTNode *p, BiTNode *q)
{
top = 0;
BiTNode *bt = root;
while(bt!=NULL || top>0)
{
while(bt != NULL)
{
//不断沿着左分支向下
s[++top].t = bt; //将当前结点入栈
bt = bt->lchild;
s[top].tag = 0; //访问左子树标志
}
while(top!=0 && s[top].tag == 1)
{
//假设p在q的左侧,那么遇到p时,栈中所有元素都是p的祖先
if(s[top].t == top)
{
//将栈的所有东西原封不变的复制到辅助栈
for(int i=0; i<=top; i++)
{
tempS[i] = s[i];
tempTop = top; //栈顶指针偏移
}
}
if(s[top].t == q)
{
//终于找到了q 元素
for(i=top; i>0; i--)
{
for(j=tempTop; j>0; j--)
{
if(tempS[j].t == s[i].t)
return s[i].t;
//找到了公共的祖先
}
}
top--; //退栈
}
}
if(top != 0)
{
s[top].tag = 1;
bt = s[top].t->rchild;
}
//沿着右分支向下遍历
}
return NULL; //找不到公共祖先,都把所有遍历了,还找不到
}