考研数据结构(每日一题)
题目:设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根结点的指针,p和q分别指向该二叉树中任意两个结点的指针,试编写算法ANCESTOR(ROOT,p,q,r)找到p和q的最近公共祖先结点r。
算法思想:
这道题的目的是了解后序遍历的特性,在遍历中,栈内元素都是当前元素的直系祖先。栈存在是意义:访问到了,但是还没有轮到它输出,因为顺序是左右根,它是根,所以现在还不能输出,入栈了,接下来访问它的左右孩子。
采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先。后序遍历必然先遍历到结点p,栈中元素均为p的祖先。先就栈复制到另一辅助栈中。继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配(相等)的元素就是结点p和q的最近公共祖先。
完整代码:
typedef struct {
BiTree t;
int tag; //tag=0表示左子女已被访问,tag=1表示右子女已被访问
}stack;
stack s[],s1[]; //定义栈,容量要足够大
BiTree Ancestor(BiTree ROOT,BiTNode *p,BiTNode *q){
top = 0;
bt = ROOT;
while (bt != NULL || top > 0)
{
while(bt != NULL){
s[++ top].t = bt;
s[top].tag = 0;
bt = bt -> lchild;
} //沿左分支向下
while(top !=0 && s[top].tag == 1){
//假设p在q的左侧,遇到p时,栈中元素均为p的祖先
if (s[top].t == p){
for (int i = 1; i <= top; i++)1 {
s1[i] = s[i];
top1 = top;
}
} //将栈s的元素转入辅助栈s1保存
if(s[top].t == q){ //找到q结点
for(i = top;i > 0;i --){ //将栈中元素的树结点到s1中去匹配
for(j = top1;j > 0;j --){
if(s1[j].t == s[i].t){
return s[i].t; //p和q的最近公共祖先已找到
}
}
}
}
top --; //退栈
}
if(top != 0){
s[top].tag = 1;
bt = s[top].t -> rchild;
} //沿右分支向下遍历
}
return NULL; //p和q无公共祖先
}