n-ary树的最低共同祖先

时间:2015-07-18 08:31:59

标签: c++ algorithm data-structures tree

我试图找出二叉树的最低共同祖先。 这是我在C ++中尝试过的,但程序停止工作(运行时错误)。 有人可以建议我如何改进吗?

另外,我知道这个程序会输出给定节点的最右边的祖先,但我无法找到找到正确LCA的方法吗?

#include<cstdio>
#include<iostream>
using namespace std;
#define MARKER ')'
#define N 5
using namespace std;

// A node of N-ary tree
struct Node {
   char key;
   Node *child[N];  // An array of pointers for N children
};


Node *newNode(char key)
{
    Node *temp = new Node;
    temp->key = key;
    for (int i = 0; i < N; i++)
        temp->child[i] = NULL;
    return temp;
}

int height(struct Node *root)
{
    if(root==NULL)
        return 0;
    int hg[N];
    int maxx=-9999;
    for(int i=0;i<N;i++)
    {
        hg[i]=height(root->child[i])+1;
        if(hg[i]>maxx)
        maxx=hg[i];
    }
    return maxx;
}
int size(struct Node*root)
{
    int sz=1;
    if(root==NULL)
    return 0;
   else
   {
    for(int i=0;i<N;i++) sz=sz+size(root->child[i]);
   } 
   return sz;
}

struct Node *LCA(struct Node *a,struct Node *b, struct Node *root)
    {
        cout<<a->key<<" "<<b->key<<endl;
        if(a==root || b==root)
            return root;


        struct Node *temp=NULL;

       for(int i=0;i<N;i++)
        {
            struct Node *res=LCA(a,b,root->child[i]);
            if(res!=NULL)
            {
                temp=res;
            }
        }

        return temp;
}

Node *createDummyTree()
{
    Node *root = newNode('A');
    root->child[0] = newNode('B');
    root->child[1] = newNode('C');
    root->child[2] = newNode('D');
    root->child[0]->child[0] = newNode('E');
    root->child[0]->child[1] = newNode('F');
    root->child[2]->child[0] = newNode('G');
    root->child[2]->child[1] = newNode('H');
    root->child[2]->child[2] = newNode('I');
    root->child[2]->child[3] = newNode('J');
    root->child[0]->child[1]->child[0] = newNode('K');
    return root;
}


void traverse(Node *root)
{
    if (root)
    {
        printf("%c ", root->key);
        for (int i = 0; i < N; i++)
            traverse(root->child[i]);
    }
}

int main()
{
        Node *root = createDummyTree();
        cout<<height(root)<<endl;
        cout<<size(root)<<endl;
        cout<<LCA(root->child[2]->child[0],root->child[2]->child[1],root)->key<<endl;


    return 0;
}

3 个答案:

答案 0 :(得分:1)

解决方案很简单我的朋友。首先,我们为每个节点都包含一个父指针和级别字段。

struct Node {
   char key;
   Node *child[N];
   Node *parent;
   int level; // An array of pointers for N children
};

现在我们将利用上述结构。

要点是首先将两个指针放在同一水平,如果这样做,它们会变得相等,那么我们就完成了,如果它们不成功,我们只需将两个指针移到上面,直到它们变为等于。多数民众赞成。

更重要的一点是,你不需要将根指针传递给LCA,所以你的主要功能是这样的:

int main()
{
        Node *root = createDummyTree();
        cout<<LCA(root->child[2]->child[0],root->child[2]->child[1])->key<<endl;
    return 0;
}

你的LCA功能就是这样。

struct Node *LCA(struct Node *a,struct Node *b)
    {
      struct Node *larger,*smaller;
      if(a->level>b->level)
        {larger=a;smaller=b;}
      else {larger=b;smaller=a;}    
      while(larger->level!=smaller->level)
         larger=larger->parent;    
      while(larger!=smaller)
      {
          larger=larger->parent;
          smaller=smaller->parent;
      }
      return larger;//you can also return smaller here.
    }

在你的createDummyTree中,你只需要设置每个节点的父级和级别,它就像这样。

Node *createDummyTree()
{
    Node *root = newNode('A');
    root->level=0;
    root->child[0] = newNode('B');
    root->child[0]->parent=root;
    root->child[0] ->level=1;
    root->child[1] = newNode('C');
    root->child[1]->parent=root;
    root->child[1] ->level=1;
    root->child[2] = newNode('D');
    root->child[2]->parent=root;
    root->child[2] ->level=1;
    root->child[0]->child[0] = newNode('E');
    root->child[0]->child[0]->parent=root->child[0];
    root->child[0]->child[0]->level=2;
    root->child[0]->child[1] = newNode('F');
    root->child[0]->child[1]->parent=root->child[0];
    root->child[0]->child[1]->level=2;
    root->child[2]->child[0] = newNode('G');
    root->child[2]->child[0]->parent=root->child[2];
    root->child[2]->child[0]->level=2;
    root->child[2]->child[1] = newNode('H');
    root->child[2]->child[1]->parent=root->child[2];
    root->child[2]->child[1]->level=2;
    root->child[2]->child[2] = newNode('I');
    root->child[2]->child[2]->parent=root->child[2];
    root->child[2]->child[2]->level=2;
    root->child[2]->child[3] = newNode('J');
    root->child[2]->child[3]->parent=root->child[2];
    root->child[2]->child[3]->level=2;
    root->child[0]->child[1]->child[0] = newNode('K');
    root->child[0]->child[1]->child[0]->parent=root->child[0]->child[1];
    root->child[0]->child[1]->child[0]->level=3;
    return root;
}

即使在最坏的情况下,上述代码也会为您提供 O(高度)的答案。

答案 1 :(得分:0)

如果你在只有向下指针的n-ary树中寻找lca,你想在树下搜索最低节点,该节点认为a和b都可以从 试着考虑这个角度

我建议创建一个方法来查找a是否是b的后代。然后我会创建一个接收节点,祖先和另外两个节点a和b的方法,并说:a和b是否可以从祖先到达?然后我会有一个函数执行以下操作:对于每个儿子,是从我儿子可以访问的a和b,返回与该儿子一起调用的这个递归函数的结果。如果没有儿子持有这个要求,我将返回父亲,如果a和b可以从他那里得到。然后我会用root作为父亲调用第三种方法,用a和b调用。希望这有帮助

答案 2 :(得分:0)

我发现了许多不同的方法来解决这个问题,例如:

  1. 跟踪节点结构(link)中每个节点的父节点
  2. 在将原始节点映射到欧拉数 (link) 或跟踪每个节点的深度 (link) 的同时使用 Euler tour
  3. 但以下小代码在我看来是最简单的:

假设:

  • 它假设两个给定的节点都存在于给定的 n 叉树中。为了修复它,我们可以运行另一种方法来首先验证它们是否都存在于树中。

它是如何工作的:

  1. 为了找到给定节点的最低公共祖先,我们需要考虑两个选项

  2. Option1:给定的两个节点都在同一个子树中,并且其中一个是最低共同祖先,这是给定算法返回temp的情况

  3. Option2:给定节点之一属于访问节点的一个子树,另一个属于另一个,在这种情况下,我们需要返回在该算法中实现的访问节点(if count==2 ) 的条件检查

    Node LCA(Node a, Node b, Node root) {
    if(a == root || b == root)
        return root;
    
    int count = 0;
    Node temp = null;
    
    for(Node iter : root.children) {
        Node res = LCA(a, b, iter);
        if(res != null) {
            count++;
            temp = res;
        }
    }
    
    if(count == 2)
        return root;    
    return temp;
    

    }