簡體   English   中英

n 叉樹的最低共同祖先

[英]lowest common ancestor of n-ary 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;
}

解決辦法很簡單,我的朋友。 首先,我們為每個節點包含一個父指針和級別字段。

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(height)的答案。

如果您正在尋找只有向下指針的 n 元樹中的 lca,您想向下搜索樹中的最低節點,該節點持有 a 和 b 都可以從嘗試考慮這個角度

我建議創建一個方法來查找 a 是否是 b 的后代。 然后我會創建一個方法來接收一個節點、祖先和另外兩個節點 a 和 b,並說:a 和 b 是否可以從祖先到達? 然后我將有一個執行以下操作的函數:對於每個兒子,我的兒子是否可以到達 a 和 b,返回該兒子調用的遞歸函數的結果。 如果沒有兒子滿足此要求,如果可以從父親那里獲得 a 和 b,我將返回父親。 然后我會調用第三個方法,以 root 為父,使用 a 和 b。 希望這可以幫助

我找到了許多不同的方法來解決這個問題,例如:

  1. 跟蹤節點結構中每個節點的父節點( 鏈接
  2. 使用歐拉回路而映射到歐拉數原始節點( 鏈路)或保持每個節點的深度的軌道(鏈路
  3. 但以下小代碼在我看來是最簡單的:

假設:

  • 它假設兩個給定的節點都存在於給定的 n 叉樹中。 為了修復它,我們可以運行另一種方法來首先驗證它們是否都存在於樹中。

它是如何工作的:

  1. 我們需要考慮兩個選項來找到給定節點的最低公共祖先

  2. 選項 1:給定的兩個節點都在同一子樹中,其中一個是最低共同祖先,這是給定算法返回 temp 的情況

  3. 選項2:給定節點之一屬於訪問節點的一個子樹,另一個屬於另一個,在這種情況下,我們需要在條件檢查(如果計數)下返回該算法中實現的訪問節點==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;

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM