[英]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:給定的兩個節點都在同一子樹中,其中一個是最低共同祖先,這是給定算法返回 temp 的情況
選項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.