数据结构小作业——求结点最近共同祖先

参考

问题描述

已知在二叉链表表示的二叉树中,root为根结点,p,q,为二叉树中两个结点,试编写算法求距离他们最近的共同祖先

思路

先举几个实例来分析一下
得出结论:1.当这两个节点在某个节点的左右子树中时,这个节点为这两个节点的最近共同祖先。2.其中一个节点为另一个节点的祖先的情况,那么这个节点的双亲就是他俩的最近共同祖先。
不管是哪种情况,都需要判断的是,一个节点是否为某一节点的子孙。

方案一

假设两个节点分别为节点A,节点B。当前节点为C
分别计算C结点左子树,右子树中节点A,B存在的个数。若左子树中节点个数=右子树中节点个数=1,那么当前结点即为最近祖先。如果左子树中节点个数=2,判断左子树根节点是否为节点A,B中的一个,如果是,那么当前结点C即为最近公共祖先。如果不是,递归,当前结点C变为C的左孩子。右子树同理。
评价:感觉好麻烦啊,一点也不简洁优雅,代码都懒得敲了

方案二

遍历左子树和右子树,假如左子树中含有A,那么返回A.含有B,则返回B。看哪个子树返回了节点就继续遍历哪个子树。如果左右子树都返回节点,那么这个就是最近公共祖先。

code

function

创建二叉树

注意这里必须用scanf才能读入空格,不能用cin

nodePtr create()
{
	char ch;
	nodePtr a;
	scanf("%c",&ch);
	if(ch == ' ')
	{
		return NULL;
	}
	else
	{
		a = new node;
		a->ch = ch;
		a->left = create();
		a->right = create();
		return a;
	}
}

找当前根节点的树中有多少个节点

void traverse(nodePtr a, char p, char q, int &k)
{
	if(a == NULL)
	{
		return;
	}
	else
	{
		if(a->ch == p || a->ch == q)
		{
			k++;	
		}
		traverse(a->left, p, q, k);
		traverse(a->right, p, q, k);
	}
}

寻找最近公共祖先

如果当前结点为节点中的一个,那么当前结点为最近公共祖先。如果当前结点左右子树中各有一个节点,那么当前结点为最近公共祖先。如果两个节点都在当前结点的左子树或者右子树中,那么他们的最近公共祖先可能在左子树或者右子树中。递归寻找即可

nodePtr find(nodePtr a, char p, char q)
{
	int left = 0, right = 0;
	traverse(a->left, p, q, left);//找到左子树中节点个数 
	traverse(a->right, p, q, right);//找到右子树中节点个数 
	cout<<"left:"<<left<<endl;
	cout<<"right:"<<right<<endl;
	if(a->ch == p || a->ch == q)//如果当前结点为其中一个 
	{
		return a;//返回当前结点 
	}
	else if(left == right)//如果当前结点左右子树各有一个节点,返回当前结点 
	{
		return a;
	}
	else
	{
		//如果两个节点都在左子树中,那么在左子树中找,反之,在右子树中找 
		if(left == 2)
		{
			find(a->left, p, q);
		}
		else
		{
			find(a->right, p, q);
		}
	}
}

#include<stdio.h>
#include<iostream>
using namespace std;
typedef struct node{
	char ch;
	struct node *left;
	struct node *right;
}node, *nodePtr;
nodePtr create();//创建一棵二叉树 
nodePtr find(nodePtr a, char p, char q);//找a树中p,q的最近祖先
void traverse(nodePtr a, char p, char q, int &k);//遍历a树,看有没有p,q 
void print(nodePtr a);//打印二叉树 
void destroy(nodePtr a);//删除二叉树 
int main()
{
	nodePtr a = create();//创建二叉树
	char p, q;
	cin>>p;
	cin>>q;
	nodePtr b = find(a, p, q);//找a树中p,q的最近祖先
	cout<<b->ch;	
	destroy(a);//释放空间 
	return 0;	 
}
nodePtr create()
{
	char ch;
	nodePtr a;
	scanf("%c",&ch);
	if(ch == ' ')
	{
		return NULL;
	}
	else
	{
		a = new node;
		a->ch = ch;
		a->left = create();
		a->right = create();
		return a;
	}
}
nodePtr find(nodePtr a, char p, char q)
{
	int left = 0, right = 0;
	traverse(a->left, p, q, left);//找到左子树中节点个数 
	traverse(a->right, p, q, right);//找到右子树中节点个数 
	cout<<"left:"<<left<<endl;
	cout<<"right:"<<right<<endl;
	if(a->ch == p || a->ch == q)//如果当前结点为其中一个 
	{
		return a;//返回当前结点 
	}
	else if(left == right)//如果当前结点左右子树各有一个节点,返回当前结点 
	{
		return a;
	}
	else
	{
		//如果两个节点都在左子树中,那么在左子树中找,反之,在右子树中找 
		if(left == 2)
		{
			find(a->left, p, q);
		}
		else
		{
			find(a->right, p, q);
		}
	}
}
void traverse(nodePtr a, char p, char q, int &k)
{
	if(a == NULL)
	{
		return;
	}
	else
	{
		if(a->ch == p || a->ch == q)
		{
			k++;	
		}
		traverse(a->left, p, q, k);
		traverse(a->right, p, q, k);
	}
}
void print(nodePtr a)
{
	if(a == NULL)
	{
		cout<<" ";
		return ;
	}
	else
	{
		cout<<a->ch;
		print(a->left);
		print(a->right);
	}
} 
void destroy(nodePtr a)
{
	if(a == NULL)
	{
		return;
	}
	else
	{
		destroy(a->left);
		destroy(a->right);
		delete a;
	}
}
/*
1.ABDH   EI   CF  GJ   |

*/
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值