
/* p、q分别为指向该二叉树中任意两个节点的指针,试编写算法ancestor(root,p,q,r),找到p、q的最近公共祖先节点r 分析: 上一道题其实可以给我们一些启示,就是我们可以将任意节点的祖先存起来,那这里我们也可以用两个栈,分别将p、q 的祖先存在栈中,因为栈顶是最近的祖先节点,所以我们可以一次往下寻找相同节点,第一次找到的相同节点便是最近公共 祖先节点。*/struct biTree { char data; struct biTree *lchild; struct biTree *rchild;};struct Stack { biTree *arr; int len; int top;};#include <stdio.h>#include <stdlib.h>void findAncestor(Stack *s, biTree *m, biTree *x) { struct biTree *r = (struct biTree *)malloc(sizeof(struct biTree)); bool empty(Stack *); bool push(Stack *, biTree*); bool pop(Stack *); biTree *top(Stack *);//返回得是一个指针 while (m || !empty(s)) { if (m) {//一路将所有左孩子入栈 push(s, m); m = m->lchild; } else {//没有左孩子, m = top(s); if (m->rchild&&r != m->rchild) { m = m->rchild; push(s, m); m = m->lchild; } else {//当既没有左孩子也没有右孩子时,该出栈了 pop(s);//被查找元素先出栈 if (m->data == x->data) {//找到了,那么如果栈中有元素,那全都是它的祖先 break; } r = m; m = NULL;//一定要将p置空,不然又会把m的左孩子入栈 } } }}void findNearestAncestor(biTree *T, biTree *p, biTree *q, biTree **r) { int count = 0; struct biTree *m = T;//另起指针m,指向根节点 void nodeNum(biTree *, int *); nodeNum(T, &count);//统计节点个数 struct Stack *sp, *sq; Stack *createStack(int); sp = createStack(count); sq = createStack(count); findAncestor(sp, m, p);//寻找p节点的祖先,放到栈中 findAncestor(sq, m, q);//寻找q节点的祖先 //经过上面的操作,栈sp和sq里面已经存好了p、q各自的祖先,接下来便是寻找最近祖先 bool contain(Stack *,biTree *); bool empty(Stack *); bool push(Stack *, biTree*); bool pop(Stack *); biTree *top(Stack *);//返回得是一个指针 while (!empty(sp)) {//当sp不空 *r = top(sp); if (contain(sq,*r)) {//判断sq中知否包含d break; } pop(sp); }}int main() { int count = 0; struct biTree *T = (struct biTree *)malloc(sizeof(struct biTree)), *p, *q; struct biTree *r = (struct biTree *)malloc(sizeof(struct biTree)); biTree *create(biTree *); T = create(T); p = T->lchild->lchild->rchild;//手动指定一个节点,切记不要指成NULL了 q = T->rchild->rchild; //p = T->lchild; //q = T->rchild; findNearestAncestor(T, p, q, &r);//记得这里要将r的地址传过去,才能进行改变 printf("p q最近公共结点为值为:%c",r->data); return 0;}