3

我知道以前有人问过类似的问题,但我认为我的解决方案要简单得多。特别是与维基百科相比。

请证明我错了!

如果您有一棵树,其节点具有给定的数据结构:

struct node
{
    node * left;
    node * right;
    node * parent;
    int key;
}

你可以写一个这样的函数:

node* LCA(node* m, node* n)
{
    // determine which of the nodes is the leftmost
    node* left = null;
    node* right = null;
    if (m->key < n->key)
    {
        left = m;
        right = n;
    }
    else
    {
        left = n;
        right = m;
    }
    // start at the leftmost of the two nodes,
    // keep moving up the tree until the parent is greater than the right key
    while (left->parent && left->parent->key < right->key)
    {
        left = left->parent;
    }
    return left;
}

这段代码非常简单,最坏的情况是 O(n),平均情况可能是 O(logn),特别是如果树是平衡的(其中 n 是树中的节点数)。

4

3 回答 3

5

您的算法对我来说看起来不错,至少我想不出更好的算法。请注意,您不需要父指针;相反,您可以从根开始向下遍历树,并找到其键位于两个初始键之间的第一个节点。

但是,您的问题与 Tarjan 解决的问题无关。首先,你考虑二叉树,他考虑n叉树;但这可能是一个细节。更重要的是,您考虑搜索树,而 Tarjan 考虑一般树(键上没有排序)。您的问题要简单得多,因为根据键,您可以猜测某个节点在树中的位置。

于 2010-11-01T19:18:45.040 回答
1

不,我很抱歉。但是你的算法不好。采取以下 BST:

10
  \
   \
   15
  / \
 14 16

你的算法将返回 10 作为最低的共同祖先。

因此,您可以编写算法,例如,获取左节点然后转到其父节点并在其上按顺序运行,并检查右节点是否在按顺序的输出中

于 2013-05-15T22:02:19.543 回答
1
Node* getAncestor( Node* root, Node* node1 , Node* node2 )
{
    if( root->val > node1->val && root->val > node2->val )
        getAncestor( root->left , node1 , node2 );
    //recursive call with left subtree

    if( root->val < node1->val && root->val < node2->val )
        getAncestor( root->right , node1 , node2 );
    //recursive call with right subtree

    return root ;
    //returning the root node as ancestor

    //initial call is made with the tree's root node
    //node1 and node2 are nodes whose ancestor is to be located


}
于 2013-06-04T07:52:12.153 回答