-
递归思想:
判断p和q是否分别根结点的左右两侧,如果在左右两侧那么直接返回根结点即可,不失一般性,假设p和q分别均在根结点的左侧,那么按照分治的思想,此时继续往左子树找即可(问题规模已经缩小),那么依旧还是上面的操作划分,故可以采用递归的思想,后序遍历,如果在左子树找到了p,那么直接返回当前的root, 继续往root的右子树找,如果找到了q,说明root即是所找结点,如果未找到,将root返回给上一层继续搜索。 -
非递归思路
通过后序遍历的思想,后序遍历存储了根结点到结点的所有祖先结点,用两个栈,假设p在q的左边,那么先找到p,栈A存储从根到p的所有祖先,栈B先拷贝栈A的数据,然后继续后序遍历,直至找到q,接着栈B开始出栈,与栈A进行比较,最先相等的结点就是最近公共祖先。
typedef struct BiTree{
struct BiTree* lchild;
struct BiTree* rchild;
int data;
}BiTree;
typedef struct{
BiTree* t;
int tag;//tag=0 表示结点的左子女已被访问,tag=1表示结点的右子女已被访问
}Stack;
//递归创建树
void CreateTree(BiTree* &node,int &i,int treeData[]){
int data = treeData[i];
if (data != -1) {
node = new BiTree();
node->data = data;
CreateTree(node->lchild,++i,treeData);
CreateTree(node->rchild,++i,treeData);
}
}
//寻找最近公共祖先结点
BiTree* CommonAncestor(BiTree* root,BiTree* p, BiTree* q){
if (root == NULL || root->data == p->data || root->data == q->data) {
return root;
}
BiTree* left = CommonAncestor(root->lchild, p, q);
BiTree* right = CommonAncestor(root->rchild, p, q);
if (left == NULL && right == NULL) {
return NULL;
}else if (left != NULL && right != NULL) {
return root;
}else if(left != NULL){
return left;
}else{
return right;
}
}
//非递归寻找最近公共祖先
BiTree* Ancestor(BiTree* root,BiTree* p,BiTree* q)//求二叉树上结点p和q的最近的共同祖先结点r。
{
cout<<"寻找p:"<<p->data<<"和q:"<<q->data<<"最近公共祖先"<<endl;
int top = 0;
int top1 = 0;
BiTree* bt = root;
Stack s[MaxSize],s1[MaxSize];//栈,容量够大
while(bt != NULL || top > 0)
{
if (bt != NULL) {
cout<<"data:"<<bt->data<<endl;
}
while(bt != NULL && bt->data != p->data && bt->data != q->data) //结点入栈
{
s[++top].t = bt;
s[top].tag = 0;
bt = bt->lchild;
} //沿左分枝向下
if (bt!=NULL) {
if(bt->data == p->data) //不失一般性,假定p在q的左侧,遇结点p时,栈中元素均为p的祖先结点
{
for(int i = 1; i <= top; i++)
s1[i] = s[i];
top1 = top;
}//将栈s的元素转入辅助栈s1 保存
}
if (bt!=NULL) {
if(bt->data == q->data) {
for(int i = top;i>0;i--)//;将栈中元素的树结点到s1去匹配
{
BiTree* pp = s[i].t;
for (int j = top1;j>0;j--)
if(s1[j].t == pp) {
cout<<"p和q的最近共同的祖先已找到"<<endl;
return pp;
}
}
}
}
while(top!=0 && s[top].tag==1)
top--; //退栈
if (top!=0){
s[top].tag=1;
bt=s[top].t->rchild;
} //沿右分枝向下遍历
}
return NULL;//q、p无公共祖先
}
int main(int argc, const char * argv[]) {
BiTree* tree = NULL;
int nodeTree[] = {1,2,3,-1,-1,4,-1,-1,5,-1,6,-1,-1};
int i = 0;
CreateTree(tree,i,nodeTree);
BiTree* p = new BiTree();
p->data = 3;
p->lchild = NULL;
p->rchild = NULL;
BiTree* q = new BiTree();
q->data = 5;
q->lchild = NULL;
q->rchild = NULL;
BiTree* low = CommonAncestor(tree, p, q);
cout<<"lca: "<< low->data << endl;
return 0;
}