Pentru un arbore binar dat găsi binar de căutare sub-arbore maxim

voturi
13

Pentru un arbore binar dat, găsi cea mai mare subarbore, care este, de asemenea, binar arbore de căutare?

Exemplu:

Intrare:

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

ieşire:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
Întrebat 02/07/2010 la 06:15
sursa de către utilizator
În alte limbi...                            


7 răspunsuri

voturi
0

Un arbore binar de căutare vă va da un rezultat sortat dacă faci un IN COMANDĂ Traversare. Deci, fă-o în ordine traversal pentru întregul arbore binar. Secvența cea mai lungă este sortata ta cea mai mare căutare binară de sub copac.

  • Face o traversal inordine de elemente (STÂNGA VIZITA, ROOT VIZITA, vizita dreapta)
  • În timp ce faci acest lucru, pentru a primi datele de nod, compara dacă datele nodul anterior este mai mică decât următoarele date. Dacă da, incrementa contor de 1. A se păstra nodul de start.
  • În cazul în care comparația nu reușește, stoca nodul final și de resetare a contorului la 0
  • Stocați aceste informații (contor, început, sfârșit) nod într-o structură de matrice pentru a găsi mai târziu, care are valoarea maximă și care vă va oferi cel mai lung binar de căutare de sub copac
Publicat 02/07/2010 la 06:26
sursa de către utilizator

voturi
2

Interesantă întrebare!

Încercarea mea a fost mai devreme greșit cântărește prostește!

Aici este o altă încercare (sperăm corecta acest timp).

Sunt presupunând copacul este conectat.

Să presupunem că pentru fiecare nod n al arborelui, ai avut un set de descendenți ai lui n, S n cu proprietatea că

  • Pentru fiecare membru al S x n , calea unică de la n la x este un binar de căutare copac (este doar o cale, dar puteți lua în considerare totuși un copac).

  • Pentru fiecare y descendent al lui x, astfel încât calea de la n la y este BST, y este în S n .

Setul de noduri S n , vă oferă cea mai mare BST înrădăcinat la n.

Putem construi S n pentru fiecare nod efectuând o căutare adâncime mai întâi pe copac, și trecând în informațiile de cale (calea de la rădăcină la nodul curent) și actualizarea seturilor de noduri din calea de backtracking de-a lungul traseului.

Când vizităm un nod, am mers pe jos în sus pe calea și verificați dacă proprietatea BST este îndeplinită pentru acel segment al căii mers în sus până în prezent. Dacă este așa, vom adăuga nodul curent la setul corespunzător nodului de calea pe care am mers la doar. Am oprit din mers pe calea momentul în care proprietatea BST este încălcat. Verificarea dacă segmentul de traseu am mers până acum este un BST se poate face în O (1) timp, pentru un timp total de prelucrare O (PATH_LENGTH) timp, pentru fiecare nod.

La final, fiecare nod va avea sale corespunzătoare S n populate. Putem merge pe jos copac acum și alege nodul cu cea mai mare valoare de S n .

Timpul necesar pentru aceasta este suma adancimi de noduri (în cel mai rău caz), și că este O (nlogn) în cazul mediu ( a se vedea secțiunea 5.2.4 din http://www.toves.org/books/ date / ch05-arbori / index.html ), dar O (n ^ 2) , în cel mai rău caz.

Poate că o modalitate de a actualiza isteți seturi va garanta o reducere în cel mai rău caz timpul.

Pseudo-cod ar putea fi ceva de genul:

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

}
Publicat 02/07/2010 la 14:13
sursa de către utilizator

voturi
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

După cum a subliniat BlueRaja, acest algoritm nu este corect.

Ar trebui să fie într - adevăr numit GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Publicat 02/07/2010 la 19:46
sursa de către utilizator

voturi
3

Algoritmul anterior (vezi revizii) a fost O(n^2)- putem generaliza O(n log n)observând faptele care:

  1. Dacă b este rădăcina cea mai mare BST și b.left.value < b.value, atunci b.lefteste de asemenea în BST (aceeași pentru b.right.value ≥ b.value)
  2. Dacă b este rădăcina cea mai mare BST și este, de asemenea, în BST, atunci fiecare nod între a și b este în BST.

Deci , dacă c este între a și b, și c nu este în BST înrădăcinat de b, nu este nici o ( din cauza (2)) . Folosind acest fapt, putem determina cu ușurință dacă un nod este în BST înrădăcinat de către orice strămoș dat. Vom face acest lucru prin care trece un nod în funcția noastră , împreună cu o listă a strămoșilor săi, și min asociate / maxValues că actualul copil-nod ar trebui să satisfacă dacă într - adevăr că strămoșul au fost rădăcina celei mai mari BST (suntem ll numesc această listă ancestorList). Vom păstra întreaga colecție a potențialelor rădăcini înoverallRootsList

Să definim o structură numită potentialRoot, după cum urmează:

Fiecare potentialRoot conține următoarele valori:
* nod : Nodul avem în vedere pentru rădăcina BST
* MINVALUE și MAXVALUE : intervalul de un alt nod trebuie să se încadreze între a face parte din BST înrădăcinat de nod (diferit pentru fiecare nod)
* subnoduri : O listă a restului nodurile din cele mai mari BST înrădăcinat de nod

Codul pseudo arata ca acest lucru (rețineți că toate listele menționate sunt liste de 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)

La final overallRootsListva fi o listă de npotentialRoots, fiecare cu o listă de subnoduri. Cel cu cea mai mare lista subnoduri este BST ta.

Deoarece există <treeHeight valori în ancestorList, atunci (presupunând că arborele este echilibrat), algoritmul se execută înO(n log n)

Publicat 02/07/2010 la 20:21
sursa de către utilizator

voturi
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)

Se pare, la fiecare nod copac exact o dată, așa că se execută în O (N).

Editare: Crud, acest lucru nu consideră că se poate lăsa unele părți ale subarborelui. Când am citit subramificație, am presupus că „întregul copac înrădăcinat la un nod“. S-ar putea reveni pentru a remedia acest lucru mai târziu.

Publicat 03/07/2010 la 01:15
sursa de către utilizator

voturi
4

Acest răspuns a conținut anterior o O (n log n) algoritm bazat pe arbori link - ul / tăiat. Aici este o simplă (n) O soluție.

Miezul este o procedură care acceptă un nod, sistemul BSST maxim unic înrădăcinat la copilul său stâng, unic maximă BSST înrădăcinat la copilul său drept, și indicii la cel mai din stânga și din dreapta-cele mai multe elemente ale acestor BSSTs. Ea distruge intrările sale (care pot fi evitate cu structuri de date persistente) și construiește BSST maxim unic înrădăcinat la nodul dat, împreună cu minimul și elementele maxime. Toate nodurile BSST sunt adnotate cu numărul de descendenți. Ca și înainte, această procedură este numită în mod repetat, de la un traversal post-comandă. Pentru a recupera sub-copac, amintiți-vă rădăcina cea mai mare BSST; reconstruirea necesită doar o simplă traversal.

Voi trata doar BSST din stânga; dreapta este simetrică. În cazul în care rădăcina BSST din stânga este mai mare decât noua rădăcină, atunci întregul sub-copac este îndepărtat, iar noua rădăcină este acum mai din stânga. În caz contrar, vechi nodul cel mai din stânga este încă mai din stânga. Pornind de la dreapta-cel mai nod al BSST stânga și se deplasează în sus, găsiți primul nod care este mai mică sau egală cu rădăcina. Copil dreptul său trebuie să fie eliminate; rețineți că acum datorită proprietății BST, nici un alt nod nevoie pentru a merge! Mai departe spre rădăcina BSST stânga, actualizarea numărătorile pentru a reflecta ștergerea.

Motivul pentru care acest lucru este O (n) este că, în ciuda buclei, fiecare margine în arborele original este în esență traversat doar o singură dată.


EDIT: în mod colectiv, traseele parcurse sunt maxime căi de linie dreaptă într-un BST, cu excepția coloanei vertebrale din stânga și din dreapta a coloanei vertebrale. De exemplu, la intrare

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

aici sunt apeluri recursive pe care este traversată fiecare muchie:

              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
Publicat 03/07/2010 la 17:46
sursa de către utilizator

voturi
1

CEL MAI MARE CAUTARE Binar TREE a arborelui:

Există două modalități prin care putem aborda această problemă,

i) Cel mai mare BST nu a indus (de la un nod, toți copiii săi nu trebuie să îndeplinească condiția BST)

ii) Cel mai mare BST indusă (de la un nod, toți copiii săi vor satisface condiția BST)

Vom discuta despre cea mai mare BST (Nu indusă) aici. Vom urmări abordarea de jos în sus (post comanda parcurgeri) pentru a rezolva acest lucru.

a) atinge nodul frunză

b) Un nod arbore (din frunze) va returna un obiect TreeNodeHelper care are următoarele câmpuri în ea.

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) Inițial din nodul frunză, noduri = 1, isBST = true, MINVALUE = MAXVALUE = node.data. Și în plus, nodurile COUNT vor fi majorate în cazul în care îndeplinește condiția BST.

d) Cu ajutorul acestui fapt, vom verifica starea BST cu nodul curent. Și vom repeta același lucru până la rădăcină.

e) De la fiecare nod două obiecte vor fi returnate. una pentru ultima BST maximă și alta pentru curent BST noduri satisfăcătoare. Deci, de la fiecare nod (deasupra frunzei) (2 + 2) = 4 (2 pentru subramificație stâng și 2 pentru sub copac dreapta) obiecte vor fi comparate și două vor fi returnate.

f) final obiect maxim nodului de rădăcină va fi cel mai mare BST

PROBLEMĂ:

Există o problemă în această abordare. În timp ce în urma acestei abordări, în cazul în care un subarborele nu îndeplinește condiția BST cu nodul curent, nu putem ignora pur și simplu subarbore (chiar și are un număr mai mic de noduri). De exemplu

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

Din nodurile frunză (20110) obiectele vor fi testate cu nod (105), acesta îndeplinește condiția. Dar când ajunge la nodul (95) nodul frunză (20) nu îndeplinește condiția BST. Deoarece această soluție este BST (nu a indus) nu ar trebui să ignore nod (105) și nodul (110) care satisface condiția. Deci, de la nodul (95), trebuie să ne intoarcem din nou de testare condiție BST și captura aceste noduri (105, 110).

Codul complet pentru această implementare este disponibil în acest link

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

Publicat 27/03/2014 la 00:48
sursa de către utilizator

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