Czy istnieje lepszy sposób na znalezienie najniższy wspólny przodek?

głosy
3

Wiem, że podobne pytania zostały poproszone wcześniej, ale myślę, że moje rozwiązanie jest znacznie prostsze. Zwłaszcza w porównaniu do Wikipedii .

Proszę udowodnić mi źle!

Jeśli masz drzewo z węzłów, które mają daną strukturę danych:

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

Można napisać funkcję tak:

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;
}

Kod ten jest dość prosty i najgorszy przypadek jest O (n), przeciętny przypadek to chyba O (logn), zwłaszcza jeśli drzewo jest zrównoważony (gdzie n to liczba węzłów w drzewie).

Utwórz 30/10/2010 o 03:26
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
5

Twój algorytm wygląda w porządku dla mnie, przynajmniej nie mogłem myśleć o niczym lepszym. Należy pamiętać, że nie trzeba wskaźnik macierzystej; zamiast tego można zejść z drzewa począwszy od korzenia i znajdź pierwszy węzeł, którego klucz leży pomiędzy dwoma początkowych kluczy.

Jednak problem nie ma nic wspólnego z jednym Tarjan rozwiązany. Przede wszystkim rozważyć drzewo binarne, a on uważa, n-ary drzew; ale to chyba szczegół. Co ważniejsze, rozważyć wyszukiwania drzew, natomiast Tarjan uważa drzew ogólne (bez zamawiania na klawiszach). Twój problem jest znacznie prostsze, ponieważ w zależności od klucza, można się domyślać, gdzie pewien węzeł ma być w drzewie.

Odpowiedział 01/11/2010 o 20:18
źródło użytkownik

głosy
1

Nie, przykro mi. Ale twój algorytm nie jest dobre. podjąć następujące BST:

10
  \
   \
   15
  / \
 14 16

Algorytm you'r powróci 10 jak najniższego wspólnego przodka.

W ten sposób można napisać algorytm, który wziąć, powiedzmy, lewy węzeł i nie iść do swojego rodzica i uruchomić w zamówienie na nim i tym sprawdzenie, czy prawo było w wyjściu z rzędu

Odpowiedział 15/05/2013 o 23:02
źródło użytkownik

głosy
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


}
Odpowiedział 04/06/2013 o 08:52
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more