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

本文介绍了一种算法来寻找二叉树中任意两个节点的最近公共祖先。针对不同类型的二叉树(如二叉搜索树、普通二叉树等),提供了具体的解决方法及实现代码。

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

(编程之美)求树中两个节点的最短公共祖先。
情况一:二叉搜索树
二叉搜索树都是排序过的,位于左子树的节点都比父节点小,而位于右子树上面的节点都比父节点大。
如果当前节点的值比两个结点 的值都大,那么最低的共同的父节点一定是在当前节点的左子树中,于是下一步遍历当前节点的左子节点。
如果当前节点的值比两个结点的值都小,那么最低的共同的父节点一定是在当前节点的右子树中,于是下一步遍历当前节点的右子节点。
这样从上到下,找到的第一个在两个输入结点的值之间的节点,就是最低的公共祖先。
情况二:这是一颗普通的树,但是有指向父节点的指针
题目等价于求解两个链表的第一个公共节点问题
情况三:这是一颗普通的树,没有指向父节点的指针
用两个链表分别保存从根节点到输入的两个结点的路径,然后把问题转换成两个链表的最后公共节点。
代码如下:


#include<iostream>
#include<list>
using namespace std;

struct TreeNode
{
    int value;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int nvalue):value(nvalue),left(NULL),right(NULL){};
};

bool GetNodepath(TreeNode* pRoot,TreeNode* pNode,TreeNode*path[15],int flag)
{
    if(pRoot==NULL)
        return false;

    path[flag++]=pRoot;
    bool found=false;
    if(pRoot==pNode)
    {
        found=true;
        return found;
    }
    found=GetNodepath(pRoot->left,pNode,path,flag)||GetNodepath(pRoot->right,pNode,path,flag);
    if(!found)
    {
            path[--flag]=NULL;

    }
    return found;
}


TreeNode*GetLastCommonNode(TreeNode* path1[15],TreeNode* path2[15])

{

    TreeNode*pLast=NULL;
    int i=0,j=0;

    while(path1[i]!=NULL&&path2[j]!=NULL)
    {
        if(path1[i]==path2[j])
            pLast=path1[i];
        i++;
        j++;
    }
    return pLast;
}

TreeNode* GetLastCommonparent(TreeNode* pRoot,TreeNode* pNode1,TreeNode* pNode2)
{
    if(pRoot==NULL||pNode1==NULL||pNode2==NULL)
        return NULL;
    TreeNode* path1[15]={NULL};
    int m=0;
    GetNodepath(pRoot,pNode1,path1,m);
    int i=0;
    while(path1[i]!=NULL)
    {
        printf("%d ",path1[i]->value);
        i++;
    }

    TreeNode* path2[15]={NULL};
    GetNodepath(pRoot,pNode2,path2,m);
    i=0;
    cout<<endl;
    while(path2[i]!=NULL)
    {
        printf("%d ",path2[i]->value);
        i++;
    }
    return GetLastCommonNode(path1,path2);
}



void main()
{
    TreeNode* p1 = new TreeNode(1);
    TreeNode *p2 = new TreeNode(2);  
    TreeNode *p3 = new TreeNode(3);  
    TreeNode *p4 = new TreeNode(4);  
    TreeNode *p5 = new TreeNode(5);  
    TreeNode *p6 = new TreeNode(6);  
    TreeNode *p7 = new TreeNode(7);  
    TreeNode *p8 = new TreeNode(8);  
    TreeNode *p9 = new TreeNode(9);  
    TreeNode *p10 = new TreeNode(10);  
    p1->left = p2;  
    p1->right=p5;
    p2->left = p3;  
    p2->right = p4;  
    p5->left = p6;  
    p5->right = p7;  
    p3->left = p8;  
    p3->right = p9;  
    p4->right = p10;  
    TreeNode *p;  
    p = GetLastCommonparent(p1 , p9 , p10);//p9和p10的最近公共祖先  
    if(p)  
        cout<<"两个节点最近公共祖先是 p"<<p->value<<endl;  
    else  
        cout<<"不存在公共祖先"<<endl;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值