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

要考虑以下三种种情况:
1:二叉树每个节点有parent

2:二叉树是搜索二叉树。

3:就是普通二叉树。

1:二叉树每个节点有parent
首先给出Node1的父节点Node1->_parent,然后将Node1的所有父节点依次和Node2->parent作比较,如果发现两个节点相等,则该节点就是最近公共祖先,直接将其返回。 如果没找到相等节点,则将Node2的所有父节点依次和Node1->pParent->pParent作比较……直到Node1->pParent==NULL。

struct BinaryTreeNode
{
    BinaryTreeNode(int& data)
    :_data(data)
    ,pLeft(NULL)
    , pRight(NULL)
    , pParent(NULL)
    {}
    int _data;
    BinaryTreeNode* pLeft;
    BinaryTreeNode* pRight;
    BinaryTreeNode* pParent;
};
BinaryTreeNode* FindParent(BinaryTreeNode*Node1, BinaryTreeNode* Node2)
{
    if (Node1==NULL||Node2==NULL)
        return NULL;
    while (Node1)
    {
        Node1 = Node1->pParent;
        while (Node2)
        {
        if (Node1 == Node2->pParent)
            return Node1;
        Node2 = Node2->pParent;
        }
    }
}

2:二叉树是搜索二叉树
公共祖先值的大小位于两个节点值大小之间

typedef struct SerchBinaryTreeNode
{
    SerchBinaryTreeNode(int& data)
    :_data(data)
    , _pLeftChild(NULL)
    , _pRighChild(NULL)
        {}
    int _data;
    SerchBinaryTreeNode* _pLeftChild;
    SerchBinaryTreeNode* _pRighChild;

}SNode;
SNode* FindParent(SNode* pRoot, SNode* Node1, SNode* Node2)
{
    if (pRoot == NULL||Node1 == NULL||Node2==NULL)
        return NULL;
    SNode* pNode = pRoot;
    while (pNode)
    {
    if ((pNode->_data >= Node1->_data&&pNode->_data < Node2->_data)|| pNode->_data >= Node2->_data&&pNode->_data < Node1->_data)
        return pNode;
    else if (pNode->_data>Node1->_data)
        //若pNode的节点值大于两个节点的值,则,两个节点的公共祖先节点肯定在PNode左子树,否则,反之
        pNode = pNode->_pLeftChild;
    else
        pNode = pNode->_pRighChild;
    }
}

3:就是普通二叉树。
如果两个节点分别在分界点的左右子树中,则最近的公共祖先节点为根节点
如果两个节点都在左子树中,则递归处理左子树,反之,处理右子树

struct BinaryTreeNode
{
    BinaryTreeNode(int& data)
:_data(data)
, _pLeftChild(NULL)
, _pRighChild(NULL)
{}
int _data;
BinaryTreeNode* _pLeftChild;
BinaryTreeNode* _pRighChild;

};
//判断节点是否在树中
bool isInTree(BinaryTreeNode* pRoot, BinaryTreeNode* Node)
{
    if (pRoot == NULL || Node == NULL)
        return false;
    //该节点为根节点
    if (pRoot == Node)
        return true;
    bool flag = isInTree(pRoot->_pLeftChild,Node);//节点是否在左子树中
    //r若不在,则在右子树中
    if (!flag)
        return isInTree(pRoot->_pRighChild,Node);
    return flag;
}

BinaryTreeNode* FindParent(BinaryTreeNode*pRoot, BinaryTreeNode*Node1, BinaryTreeNode*Node2)
{
    //判断Node1是否在左子树中
    if (isInTree(pRoot->_pLeftChild, Node1))
    {
        //判断Node2是否在右子树
        if (isInTree(pRoot->_pRighChild, Node2))
            return pRoot;
        else//两节点都在左子树中
            return FindParent(pRoot->_pLeftChild,Node1,Node2);
    }
    else//此时Node1在右子树中
    {
        //判断Node2是否在左子树中
        if (isInTree(pRoot->_pLeftChild, Node2))
            return pRoot;
        else//两个节点都在左右子树中
            return FindParent(pRoot->_pRighChild,Node1,Node2);
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值