Per un dato albero binario trovare la massima binario di ricerca sub-albero

voti
13

Per un dato albero binario, trova la più grande sotto-albero che è anche albero binario di ricerca?

Esempio:

Ingresso:

                   10
               /         \
             50           150
            /  \         /   \
          25    75     200    20
         / \   / \    /  \    / \
        15 35 65 30  120 135 155 250 

Produzione:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
È pubblicato 02/07/2010 alle 06:15
fonte dall'utente
In altre lingue...                            


7 risposte

voti
0

Un albero binario di ricerca vi darà un risultato ordinato se si fa un in-order Traversal. Quindi, fare un attraversamento in ordine per l'intero albero binario. La sequenza più lunga ordinato è il tuo più grande sub albero binario di ricerca.

  • Fare un attraversamento in ordine simmetrico di elementi (VISITA A SINISTRA, VISITA ROOT, VISITA A DESTRA)
  • Mentre in questo modo, ottenere i dati del nodo, confrontare se i dati nodo precedente è minore rispetto ai dati successivi. Se è così, incrementare il contatore di 1. Conservare il nodo di partenza.
  • Quando il confronto ha esito negativo, memorizzare il nodo finale e resettare il contatore a 0
  • Memorizzare queste informazioni (contatore, inizio, fine) il nodo in una struttura a matrice per trovare in seguito che sta avendo il valore massimo e che vi darà il sub albero binario di ricerca più lunga
Risposto il 02/07/2010 a 06:26
fonte dall'utente

voti
2

Domanda interessante!

Il mio tentativo precedente era stupidamente sbagliato!

Qui è un altro tentativo (si spera correggere questa volta).

Io parto dal presupposto che l'albero è collegato.

Supponiamo che per ogni nodo n dell'albero, si aveva una serie di discendenti di n, S n con la proprietà che

  • Per ogni membro x di S n , il percorso unico da n per x è un Binary Search albero (è solo un percorso, ma è ancora possibile considerarlo un albero).

  • Per ogni y discendente di x, tale che il percorso da n per y è un BST, y è in S n .

L'insieme di nodi S n , offre la più grande BST radicata al n.

Possiamo costruire S n per ciascun nodo eseguendo una ricerca in profondità sull'albero, e passando le informazioni sul percorso (il percorso dalla radice al nodo corrente) e l'aggiornamento dei set di nodi nel percorso dal backtracking lungo il percorso.

Quando visitiamo un nodo, camminiamo su per il sentiero, e verifichiamo se la proprietà BST è soddisfatto per quel segmento del percorso si avvicinò finora. In caso affermativo, si aggiunge il nodo corrente alla serie corrispondente del nodo del percorso abbiamo raggiunto. Smettiamo a piedi il percorso Attualmente la proprietà BST è violata. Verificando segmento del percorso siamo entrati finora è un BST può essere realizzata in O (1) tempo, per un tempo totale O (PATH_LENGTH) tempo, per ogni nodo.

Alla fine, ogni nodo avrà il suo corrispondente S n popolato. Possiamo camminare l'albero ora e scegliere il nodo con il più grande valore di S n .

Il tempo impiegato per questo è la somma delle profondità dei nodi (nel caso peggiore), e che è O (nlogn) nel caso medio (vedere Sezione 5.2.4 http://www.toves.org/books/ dati / CH05-alberi / index.html ), ma O (n ^ 2) nel caso peggiore.

Forse un modo più intelligente per aggiornare i set garantirà una riduzione del tempo di caso peggiore.

La pseudo-codice potrebbe essere qualcosa del tipo:

static Tree void LargestBST(Tree t)
{
    LargestBST(t, new List<Pair>());
    // Walk the tree and return the largest subtree with max |S_n|.
}

static Tree LargestBST(Tree t, List<Pair> path)
{
    if (t == null) return;

    t.Set.Add(t.Value);

    int value = t.Value;
    int maxVal = value;
    int minVal = value;

    foreach (Pair p in path)
    {
        if (p.isRight)
        {
            if (minVal < p.node.Value)
            {
                break;
            }
        }

        if (!p.isRight)
        {
            if (maxVal > p.node.Value)
            {
                break;
            }
        }

        p.node.Set.Add(t.Value);

        if (p.node.Value <= minVal)
        {
            minVal = p.node.Value;
        }

        if (p.node.Value >= maxVal)
        {
            maxVal = p.node.Value;
        }
    }

    Pair pl = new Pair();
    pl.node = t;
    pl.isRight = false;

    path.Insert(0, pl);
    LargestBST(t.Left, path);

    path.RemoveAt(0);

    Pair pr = new Pair();
    pr.node = t;
    pr.isRight = true;

    path.Insert(0, pr);

    LargestBST(t.Right, path);

    path.RemoveAt(0);

}
Risposto il 02/07/2010 a 14:13
fonte dall'utente

voti
0
GetLargestSortedBinarySubtree(thisNode, ref OverallBestTree)
    if thisNode == null
        Return null
    LeftLargest = GetLargestSortedBinarySubtree(thisNode.LeftNode, ref OverallBestTree)
    RightLargest = GetLargestSortedBinarySubtree(thisNode.RightNode, ref OverallBestTree)
    if LeftLargest.Max < thisNode.Value & RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, RightLargest)
    else if LeftLargest.Max < thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, null)
    else if RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(null, thisNode.Value, RightLargest)
    else
        currentBestTree = new BinaryTree(null, thisNode.Value, null)
    if (currentBestTree.Size > OverallBestTree.Size)
        OverallBestTree = currentBestTree
    return currentBestTree

Come BlueRaja sottolineato, questo algoritmo non è corretto.

E 'in realtà dovrebbe essere chiamato GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Risposto il 02/07/2010 a 19:46
fonte dall'utente

voti
3

L'algoritmo precedente (vedi revisioni) era O(n^2)- possiamo generalizzare a O(n log n)notando i fatti che:

  1. Se b è la radice del più grande BST e b.left.value < b.value, quindi b.leftè anche nel BST (uguale per b.right.value ≥ b.value)
  2. Se b è la radice del più grande BST ea è anche nel BST, allora ogni nodo fra A e B è nel BST.

Quindi, se c è tra A e B, e C non è nel BST radicata da B, nessuno dei due è un (a causa di (2)) . Usando questo fatto, si può facilmente determinare se un nodo è nel BST radicato da qualsiasi antenato. Lo faremo passando un nodo nella nostra funzione insieme a un elenco dei suoi antenati, e il minimo associato / maxValues che l'attuale bambino nodo sarebbe da soddisfare se davvero che antenato fosse la radice del più grande BST (noi' ll chiamare questa lista ancestorList). Ci memorizzare l'intera collezione di potenziali-roots inoverallRootsList

Definiamo una struttura chiamata potentialRoot come segue:

Ogni potentialRoot contiene i seguenti valori:
* nodo : Il nodo stiamo considerando per la radice del BST
* minValue e maxValue : la gamma altro nodo deve essere compreso tra a far parte della BST radicato per nodo (diversa per ogni nodo)
* sottonodi : un elenco di tutto il resto dei nodi nel più grande BST radicata per nodo

La pseudo codice simile a questo (notare che tutti gli elenchi di cui sono liste di potentialRoots) :

FindLargestBST(node, ancestorList):
    leftList, rightList = empty lists
    for each potentialRoot in ancestorList:
        if potentialRoot.minValue < node.Value ≤ potentialRoot.maxValue:
            add node to potentialRoot.subNodes (due to (1.))
            (note that the following copies contain references, not copies, of subNodes)
            add copy of potentialRoot to leftList, setting maxValue = node.Value
            add copy of potentialRoot to rightList, setting minValue = node.Value

    add the potentialRoot (node, -∞, +∞) to leftList, rightList, and overallRootsList
    FindLargestBST(node.left, leftList)
    FindLargestBST(node.right, rightList)

Alla fine overallRootsListsarà un elenco di npotentialRoots, ciascuno con un elenco di sottonodi. Quello con la più grande lista sottonodi è il vostro BST.

Dato che ci sono <treeHeight Valori in ancestorList, allora (supponendo che l'albero è bilanciato), l'algoritmo viene eseguito inO(n log n)

Risposto il 02/07/2010 a 20:21
fonte dall'utente

voti
0
root(Tree L A R) = A

MaxBST(NULL) = (true, 0, NULL)
MaxBST(Tree L A R as T) = 
  let
    # Look at both children
    (L_is_BST, L_size, L_sub) = MaxBST(L)
    (R_is_BST, R_size, R_sub) = MaxBST(R)
  in
  # If they're both good, then this node might be good too
  if L_is_BST and R_is_BST and (L == NULL or root(L) < A) and (R == NULL or A < root(R))
  then (true, 1 + L_size + R_size, T)
  else
       # This node is no good, so give back the best our children had to offer
       (false, max(L_size, R_size), if L_size > R_size then L_sub else R_sub)

Sembra ad ogni nodo della struttura esattamente una volta, quindi viene eseguito in O (N).

Edit: Crud, questo non ritiene che si può lasciare fuori alcune parti di una sottostruttura. Quando ho letto sotto-albero, ho assunto "l'intero albero radice in qualche nodo". Posso tornare a risolvere questo problema in seguito.

Risposto il 03/07/2010 a 01:15
fonte dall'utente

voti
4

Questa risposta in precedenza conteneva un O (n log n) algoritmo basato su alberi di collegamento / taglio. Ecco una semplice (n) O soluzione.

Il nucleo è una procedura che accetta un nodo, l'unica BSST massima radicata al suo figlio sinistro, l'unica massima BSST radicato al suo figlio destro, e puntatori ai più a sinistra e più a destra di questi elementi BSSTs. Distrugge i suoi ingressi (evitabili con strutture dati persistenti) e costruisce la BSST massimo univoco radicato al nodo dato, insieme al suo minimo e massimo elementi. Tutti i nodi BSST sono annotati con il numero di discendenti. Come in precedenza, questa procedura viene chiamata più volte da un attraversamento post-ordine. Per recuperare il sub-albero, ricorda la radice del grande BSST; ricostruendo richiede solo un semplice attraversamento.

Io tratterò l'BSST solo a sinistra; il diritto è simmetrica. Se la radice del BSST sinistro è maggiore della nuova radice, allora l'intero sottoalbero viene rimosso, e la nuova radice sta più a sinistra. In caso contrario, il vecchio nodo più a sinistra è ancora più a sinistra. Partendo dalla più a destra nodo del BSST sinistra e movimento verso l'alto, per il primo nodo che è minore o uguale alla radice. Il suo figlio destro deve essere rimosso; notare ora che a causa della proprietà BST, nessun altro nodo bisogno di andare! Procedere alla radice del BSST sinistra, aggiornando i conteggi in modo da riflettere l'eliminazione.

La ragione per questo è O (n) è che, nonostante il ciclo, ciascun bordo nella struttura originale è sostanzialmente attraversato solo una volta.


EDIT: collettivamente, i percorsi attraversati sono i massimi percorsi rettilinei in un BST, fatta eccezione per la colonna vertebrale sinistra e destra della colonna vertebrale. Ad esempio, sull'ingresso

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / \             / \
    /   \           /   \
   /     \         /     \
  B       F       J       N
 / \     / \     / \     / \
A   C   E   G   I   K   M   O

ecco le chiamate ricorsive su cui è attraversato ogni bordo:

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / h             h \
    /   h           h   \
   /     h         h     \
  B       F       J       N
 / d     d h     h l     l \
A   C   E   G   I   K   M   O
Risposto il 03/07/2010 a 17:46
fonte dall'utente

voti
1

GRANDE BINARIO RICERCA ALBERO IN UN ALBERO BINARIO:

Ci sono due modi in cui possiamo affrontare questo problema,

i) più grande BST non indotta (da un nodo, tutti i suoi figli non devono soddisfare la condizione BST)

ii) più grande BST indotti (Da un nodo, tutti i suoi figli soddisfare la condizione BST)

Si discuterà sul più grande BST (non indotta) qui. Seguiremo approccio bottom up (Post ordine di attraversamento) per risolvere questo problema.

a) pervenire al nodo foglia

b) Un nodo albero (dalla foglia) restituirà un oggetto TreeNodeHelper che ha i seguenti campi in esso.

public static class TreeNodeHelper {
        TreeNode node;
        int nodes;
        Integer maxValue;
        Integer minValue;
        boolean isBST;


        public TreeNodeHelper() {}

        public TreeNodeHelper(TreeNode node, int nodes, Integer maxValue, Integer minValue, boolean isBST) {
            this.node = node;
            this.nodes = nodes;
            this.maxValue = maxValue;
            this.minValue = minValue;
            this.isBST = isBST;
        }      
    }

c) Inizialmente dal nodo foglia, nodi = 1, isBST = true, minValue = maxValue = node.data. E ancora, i nodi contare saranno aumentate se soddisfa la condizione BST.

d) Con l'aiuto di questo, si provvederà a controllare la condizione BST con nodo corrente. E noi ripetere la stessa fino a radice.

e) da ogni nodo saranno restituiti due oggetti. uno per ultima BST massimo e un altro per BST corrente nodi soddisfacenti. Così da ogni nodo (sopra foglio) (2 + 2) = 4 (2 per sottoalbero sinistro e 2 per l'albero secondario destra) oggetti verranno confrontati e due saranno restituiti.

f) L'oggetto nodo finale massimo dalla radice sarà il più grande BST

PROBLEMA:

C'è un problema in questo approccio. Pur seguendo questo approccio, se una sottostruttura non è soddisfacente la condizione BST con il nodo corrente, non possiamo semplicemente ignorare la sottostruttura (anche ha meno numero di nodi). Per esempio

 55
  \
   75
  /  \
 27  89
    /  \
   26  95
      /  \
     23  105
         /  \
        20  110

Dai nodi foglia (20.110) gli oggetti saranno testati con il nodo (105), soddisfa la condizione. Ma quando raggiunge il nodo (95) del nodo foglia (20) non soddisfa la condizione BST. Poiché questa soluzione è per BST (non indotta) non dovremmo ignorare nodo (105) e il nodo (110) che soddisfa la condizione. Così dal nodo (95) dobbiamo tornare indietro di nuovo far controllare lo stato BST e catturare quei nodi (105, 110).

Il codice completo per questa implementazione è disponibile in questo link

https://github.com/dineshappavoo/Implementation/tree/master/LARGEST_BST_IN_BT_NOT_INDUCED_VER1.0

Risposto il 27/03/2014 a 00:48
fonte dall'utente

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