求两个节点的最近公共祖先节点

本文介绍了如何在具有父节点指针的二叉树中找到两个节点的最近公共祖先。通过递归算法,利用二叉搜索树的特性,当节点分别位于左右子树或都在同一子树中时,可以确定最近公共祖先的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解法分三种情况:

1.节点有parent,即是三叉链。若是每个节点都有指向父节点的指针,则问题可以变形成求链表相交节点问题。这时就可以让路径长的节点先走几步,接着同时走,判断两个节点是否相等。

int GetLength(Node *node)
	{
		if (node == NULL)
			return 0;
		int len = 0;
		while (node)
		{
			node = node->_parent;
			len++;
		}
		return len;
	}
	//求两个节点的最近公共祖先,有指向父节点的指针的情况,转化为求两个链表的交点问题
	Node *FindCommonAncestor(Node *node1, Node *node2)
	{
		if (_root == NULL || node1 == NULL || node2 == NULL)
			return NULL;
		Node* LongLen = NULL;
		Node* ShortLen = NULL;
		//分别求出从两个节点到跟节点的路径
		int len1 = GetLength(node1);
		int len2 = GetLength(node2);
		int temp = abs(len1 - len2); //求出两个路径之差
		
		if (len1 > len2)
		{
			LongLen= node1;
			ShortLeng = node2;
		}
		else
		{
			LongLen= node2;
			ShortLen = node1;
		}
		//让路径较长的先走
		for (int i = 0; i < temp; i++)
			LongLeng = LongLeng->_parent;
		//接下来一起向前走,直到找到公共节点停止
		while (LongLen&& ShortLen && (LongLen->_data != ShortLen->_data))
		{
			LongLen = LongLen->_parent;
			ShortLen = ShortLen->_parent;
		}
		//直到找到公共节点
		if (LongLen->_data == ShortLen->_data)
			return LongLen;
		else 
			return NULL;

	}

2.二叉树是二叉搜索树


 可使用递归算法解决,根据搜索二叉树左子树的所有节点比根节点小,右子树的所有节点比跟节点大的性质,若两个节点都比根结点小,则递归左子树,若都比根结点大,则递归右子树,若两个节点一左一右,就可找出当前节点,此时当前节点是最近公共祖先 。

Node* _FindCommonAncestor(Node *&root,Node *&node1, Node *&node2)
    {
        if (_root == NULL || node1 == NULL || node2 == NULL)
            return ;
        //1.两个节都小于根节点,最近公共祖先在左子树中
        if ((node1->_data < root->_data) && (node2->_data < root->_data))
            _FindCommonAncestor(root->_left, node1, node2);
        //2.两个节都大于根节点,最近公共祖先在右子树中
        else if ((node1->_data> root->_data) && (node2->_data > root->_data))
            _FindCommonAncestor(root->_right, n1, n2);
        else //3.一个在左子树,一个在右子树,找到公共祖先root
            return root;
    }
3.二叉树是普通树
                                                                                                                                                                                                                                                              

      从根节点开始遍历,如果node1和node2中的任一个和root匹配,那么root就是最近公共祖先。 如果都不匹配,则分别递归左、右子树,如果有一个 节点出现在左子树,并且另一个节点出现在右子树,则root就是最近公共祖先.  如果两个节点都出现在左子树,则说明最近公共祖先在左子树中,否则在右子树

BinaryNode* GetLastCommonAncestor(Node *root, Node *node1, Node *node2)  
{  
    if (root == NULL || node1 == NULL || node2 == NULL)  
        return NULL;  
  
    if (node1 == root || node2 == root)  
        return root;  
  
    BinaryNode* Left_Lca = GetLastCommonAncestor(root->_left, node1, node2);  
    BinaryNode* Right_Lca = GetLastCommonAncestor(root->_right, node1, node2);  
    if (Left_Lca && Right_Lca)  
        return root;  
    if (Left_Lca == NULL)  
        return Right_Lca;  
    else  
        return Left_Lca;  
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值