C语言二叉树查找最近公共祖先(不包括查找点本身)

给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的data值 p 和 q,请找到 p 和 q 的最近公共祖先节点。要注意的是不包括p q点本身,也就是说a b c d * * * * *的二叉树中,c d公共祖先是b而不是c。

本题不认为查找点本事(p q)是祖先结果,故不能用寻常的递归解决,我在普通递归的基础上加了额外判断结果是否为p q的语句,如果是的话则证明查找点在同侧则使用travel函数重新查找

题主建议先把普通递归理解完了再理解此题,多少有些绕,我想了很久。

哎继续加油吧 

如果有错或者更好的办法欢迎评论区指正~

【输入样例】a b c d * * * * *

                      c d

【输出结果】b


typedef struct BitNode
{
	char data;
	BitNode *lchild,*rchild;
	int flag;
 }BitNode,*Bitree;


typedef struct LinkNode
{
	BitNode *data;
	LinkNode *next;
}LinkNode;
typedef struct 
{
	LinkNode *front,*rear;
}Linkque;

void Initque(Linkque &q)
{
	q.front=q.rear=(LinkNode *)malloc(sizeof(LinkNode));
	q.front->next=NULL;
}
int isempty(Linkque q)
{
	if(q.front==q.rear) return 0;
	else return 1;
}
void enque(Linkque &q,BitNode *x)
{
	LinkNode *s;
	s=(LinkNode *)malloc(sizeof(LinkNode));
	if(s!=NULL)
	{
		s->data=x;
		s->next=NULL;
		q.rear->next=s;
		q.rear=s;
	}
}
bool deque(Linkque &q,Bitree &x)
{
	if(q.front==q.rear) return false;//队空
	else
	{
		LinkNode *p=q.front->next;
		x=p->data;
		q.front->next=p->next;
		if(p==q.rear)
		{
			q.rear=q.front;
		}
		free(p);
		return true;
	 } 
}
void Precreat(Bitree &T) //根左右 
{
	char ch;
	scanf("%c",&ch);
	getchar();
	if(ch=='*') T=NULL;
	else
	{
		BitNode *s=(BitNode *)malloc(sizeof(BitNode));
		s->data=ch;
		T=s;
		Precreat(T->lchild);
		Precreat(T->rchild);
	}
 } 
 
 void Levelorder(Bitree T) //层次遍历 
{
	Linkque q;
	Initque(q);
	BitNode *s;
	enque(q,T);
	T->flag=1;
	while(isempty(q)!=0)
	{
		deque(q,s);
//	printf("%c (%d)",s->data,s->flag);
		
		if(s->lchild!=NULL)
		{
			enque(q,s->lchild);
			s->lchild->flag=s->flag+1;
		}
		if(s->rchild!=NULL)
		{
			enque(q,s->rchild);
			s->rchild->flag=s->flag+1;
		}
	}
}
int findp=0,findq=0;
void Preorder(Bitree T,char p,char q)      //先序遍历 根左右 
{
	if(T!=NULL)
	{
	//	printf("%c ",T->data);
		if(T->data==p) findp=T->flag;
		if(T->data==q) findq=T->flag;
		Preorder(T->lchild,p,q);
		Preorder(T->rchild,p,q); 
	} 
	
}
BitNode *travel1(Bitree T,char p,char q)//最近共同祖先
{
	if(T==NULL) return T;
	if(T->data==p || T->data==q) return T;
	BitNode *left=travel1(T->lchild,p,q);
	BitNode *right=travel1(T->rchild,p,q);
	if(left==NULL &&right !=NULL) return right;
	if(left!=NULL &&right ==NULL) return left;
	if(left!=NULL &&right !=NULL) return T;
	else return NULL;
}
BitNode * travel(Bitree T,char p,char q)
{
	if(T->data==p ||T->data==q) return T;	
	Linkque q1;
	Initque(q1);
	BitNode *s;
	enque(q1,T);
	int min;
	if(findp>findq) min=findq;
	else min=findp;
//	printf("min=%d",min);
	while(isempty(q1)!=0)
	{
		deque(q1,s);
		if(s->lchild!=NULL)
		{
			if(s->lchild->data==p || s->lchild->data==q) return s;
		}
		if(s->rchild!=NULL)
		{
			if(s->rchild->data==p || s->rchild->data==q) return s;
		}
		
		{
			if(s->lchild!=NULL && s->lchild->flag<=min-1)
		{
			enque(q1,s->lchild);
		}
		if(s->rchild!=NULL && s->rchild->flag<=min-1)
		{		
			enque(q1,s->rchild);	
		}
		}		
		
	}
 } 
main()
 {
 	Bitree T;
 	Precreat(T);
 	BitNode *z;
 	char p,q;
 	scanf("%c",&p);
 	getchar();
 	scanf("%c",&q);
 	getchar();
 	Levelorder(T);
 	Preorder(T,p,q);
 //	printf("%d %d",findp,findq);
 	int gtr=1;
 	z=travel1(T,p,q);
 	if(z->data==p || z->data==q) gtr=0;
 	if(gtr==0)
 	{
 		z=travel(T,p,q);
	}
	
 	printf("%c",z->data);
 	return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值