求二叉树的任意两个节点的最近公共祖先



转自:http://eriol.iteye.com/blog/1170465


二叉查找树

 

如果该二叉树是二叉查找树,那么求解LCA十分简单。

基本思想为:从树根开始,该节点的值为t,如果t大于t1和t2,说明t1和t2都位于t的左侧,所以它们的共同祖先必定在t的左子树中,从t.left开始搜索;如果t小于t1和t2,说明t1和t2都位于t的右侧,那么从t.right开始搜索;如果t1<t< t2,说明t1和t2位于t的两侧,那么该节点t为公共祖先。

如果t1是t2的祖先,那么应该返回t1的父节点;同理,如果t2是t1的祖先,应该返回t2的父节点。

 

public int query(Node t1, Node t2, Node t) {
	int left = t1.value;
	int right = t2.value;
	Node parent = null;
		
	if (left > right) {
		int temp = left;
		left = right;
		right = temp;
	}
		
	while (true) {
		if (t.value < left) {
			parent = t;
			t = t.right;
		} else if (t.value > right) {
			parent = t;
			t = t.left;
		} else if (t.value == left || t.value == right) {
			return parent.value;
		} else {
			return t.value;
		}
	}
}

一般的二叉树

 

如果二叉树不是二叉查找树该怎么办呢?

 

 

1. 离线算法(Tarjan)

利用并查集优越的时空复杂度,可以实现O(n+q)的算法,q是查询次数。

Tarjan算法基于深度优先搜索。对于新搜索到的一个结点u,先创建由u构成的集合,再对u的每颗子树进行搜索,每搜索完一棵子树,这时候子树中所有的结点的最近公共祖先就是u了。

void LCA(int parent)       //从根节点开始
{
	p[parent] = parent;
	ancestor[findSet(parent)] = parent;
	for(int i = index[parent]; i != -1; i = e[i].next)
	{
		LCA(e[i].to);
		Union(parent,e[i].to);
		ancestor[findSet(parent)] = parent;
	}
	vis[parent] = true;
	if(parent == a && vis[b])	//要先将所有查询记录下来,这里只有一个查询:a与b的LCA
		printf("%d\n",ancestor[findSet(b)]);
	else if(parent == b && vis[a])
		printf("%d\n",ancestor[findSet(a)]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值