For en gitt binærtre finne maksimal binære søk sub-treet

stemmer
13

For en gitt binært tre, finner det største treet som også er binært søketre?

Eksempel:

inngang:

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

Produksjon:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
Publisert på 02/07/2010 klokken 05:15
kilden bruker
På andre språk...                            


7 svar

stemmer
0

En binært søketre vil gi deg en sortert resultat hvis du gjør en IN-ORDER overgang. Så, en in-order traversering for hele binære treet. Den lengste sortert sekvens er din største binære søk sub treet.

  • Gjør en inorder traversering av elementer (besøk forlatt, VISIT ROOT, besøk rett)
  • Mens du gjør det, får noden data, sammenligne om den forrige noden data er mindre enn de neste data. I så fall øke teller med 1. Lagre start node.
  • Når sammenligningen mislykkes, lagre endenode og tilbakestille telleren til 0
  • Lagrer denne informasjonen (teller, start, slutt) node i en matrise struktur til senere finner noe som er å ha maksimal verdi og som vil gi deg den lengste binære søk sub treet
Svarte 02/07/2010 kl. 05:26
kilden bruker

stemmer
2

Interessant spørsmål!

Min tidligere forsøk var imbecilt galt!

Her er et annet forsøk (forhåpentligvis riktig denne gangen).

Jeg antar treet er tilkoblet.

Anta for hver node n av treet, hadde du et sett med etterkommere av n, S n med den egenskapen at

  • For hvert element xi S n , den unike banen fra n til x er et binært søketre (det er bare en vei, men du kan likevel vurdere det et tre).

  • For hver etterkommer y til x, slik at banen fra n til y er en BST, y er i S n .

Settet av noder S n , gir deg den største BST forankret n.

Vi kan konstruere S n for hver node ved å gjøre en dybde første søk på treet, og passerer i det baneinformasjon (banen fra rot til den aktuelle node), og oppdatering av settene av nodene i banen ved tilbakesporing langs banen.

Når vi besøker en node går vi opp stien, og se om BST eiendommen er fornøyd for det segmentet av banen gikk opp så langt. I så fall legger vi den aktuelle noden til tilsvarende sett av noden av banen vi bare gikk til. Vi slutter å vandre banen øyeblikket BST eiendommen er krenket. Å sjekke om det banesegmentet vi gått så langt er et BST kan gjøres i O (1) tid for en O (PATH_LENGTH) tid total behandlingstid, for hver node.

Ved slutten, vil hver node ha sin tilsvarende S n befolket. Vi kan gå treet nå og plukke noden med den største verdien av S n .

Den tiden det tar for dette er summen av dybden av nodene (i verste fall), og det er O (nlogn) i det gjennomsnittlige tilfelle (se avsnitt 5.2.4 for http://www.toves.org/books/ data / ch05-trær / indeks.html ), men O (n ^ 2) i det verste tilfelle.

Kanskje en smartere måte å oppdatere settene vil garantere en reduksjon i verste fall tid.

Den pseudo-kode kan være noe sånt som:

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

}
Svarte 02/07/2010 kl. 13:13
kilden bruker

stemmer
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

Som BlueRaja påpekt, er denne algoritmen ikke riktig.

Det bør virkelig bli kalt GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Svarte 02/07/2010 kl. 18:46
kilden bruker

stemmer
3

Den forrige algoritmen (se revisjoner) var O(n^2)- vi kan generalisere det til O(n log n)ved å merke de fakta som:

  1. Hvis b er roten av de største BST og b.left.value < b.value, så b.lefter også i BST (samme for b.right.value ≥ b.value)
  2. Hvis b er roten av de største BST og en er også i BST, deretter hver node mellom a og b er i BST.

Slik at hvis c er mellom a og b, og c er ikke i BST forankret ved b, heller ikke er en (på grunn av (2.)) . Ved hjelp av dette faktum, kan vi lett finne ut om en node er i BST forankret ved enhver stamfar. Vi vil gjøre dette ved å sende en node i vår funksjon sammen med en liste over sine forfedre, og den tilhørende min / maxValues at dagens barnenode måtte tilfredsstille så sant som stamfar var roten av de største BST (Vi ll kaller denne listen ancestorList). Vi vil lagre hele samlingen av potensielle-røtter ioverallRootsList

La oss definere en struktur kalt potentialRoot som følger:

Hver potentialRoot inneholder følgende verdier:
* node : Noden vi vurderer for roten av BST
* MINVALUE og MAXVALUE : omfanget annen node må falle mellom å være en del av BST forankret ved node (forskjellig for hver node)
* subnodes : En liste over resten av nodene i den største BST forankret ved noden

Pseudo koden ser slik ut (merk at alle listene nevnt er lister over 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)

På slutten overallRootsListvil være en liste over npotentialRoots, hver med en liste over noder. Den med de største undernoder listen er din BST.

Siden det er <treeHeight verdier i ancestorList, deretter (forutsatt at treet er balansert), går algoritmenO(n log n)

Svarte 02/07/2010 kl. 19:21
kilden bruker

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

Ser ved hver trenode nøyaktig en gang, så løper i O (N).

Edit: Crud, betyr ikke tenker på at det kan la ut noen deler av et subtre. Da jeg leste treet, antok jeg "hele treet forankret på et node". Jeg kan komme tilbake for å fikse dette senere.

Svarte 03/07/2010 kl. 00:15
kilden bruker

stemmer
4

Dette svaret tidligere inneholdt en O (n log n) algoritme basert på link / kutte trær. Her er en enklere O (n) oppløsning.

Kjernen er en prosedyre som aksepterer en node, den unik høyeste BSST forankret ved sin venstre barn, den unik høyeste BSST forankret ved sin høyre barn, og pekere til de lengst til venstre og lengst mot høyre elementene i disse BSSTs. Det ødelegger sine innganger (unngått med vedvarende datastruktur) og konstruerer den unike maksimale BSST forankret ved den gitte node, sammen med dens minimums- og maksimums-elementer. Alle BSST noder er annotert med antallet etterkommere. Som før, er denne prosedyren kalles gjentatte ganger fra en post-order traversering. For å gjenopprette sub-treet, husk roten av de største BSST; rekonstruere det krever bare en enkel traversering.

Jeg skal behandle kun den venstre BSST; høyre er symmetrisk. Dersom roten av den venstre BSST er større enn den nye rot, da hele den sub-treet er fjernet, og den nye roten er nå helt til venstre. Ellers er det gamle venstre mest node fortsatt igjen lengst. Ved å starte fra det lengst til høyre noden til venstre BSST og beveger seg oppover, finn den første noden som er mindre enn eller lik roten. Sin rett barnet må fjernes; merk nå at på grunn av BST eiendom, ingen andre noder må gå! Fortsett til roten av venstre BSST, oppdatere teller for å gjenspeile slettingen.

Grunnen til dette er O (n) er at på tross av sløyfen, blir hver kant i det opprinnelige tre i hovedsak gjennomstrømmes bare en gang.


EDIT: heretter kalt baner som gjennomløpes er den maksimale lineære baner i en BST, med unntak av den venstre ryggraden og den høyre ryggraden. For eksempel, på inngangen

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

her er de rekursive samtaler på hvilken hver kant er traversert:

              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
Svarte 03/07/2010 kl. 16:46
kilden bruker

stemmer
1

STØRSTE binært søketre i et binært TREE:

Det er to måter vi kan nærme seg dette problemet,

i) største BST ikke indusert (Fra en node, trenger alle sine barn ikke tilfredsstiller BST tilstand)

ii) Største BST indusert (fra en node, vil alle de underordnede tilfredsstiller den betingelse BST)

Vi vil diskutere om den største BST (Ikke Induced) her. Vi vil følge bottom up tilnærming (Post for traversering) for å løse dette.

a) Nå bladnoden

b) Et tre node (fra bladet) vil returnere et TreeNodeHelper objekt som har følgende felter i det.

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) Til å begynne med fra bladnoden, noder = 1, isBST = true, MINVALUE = MAXVALUE = node.data. Og videre, nodene telle skal økes dersom den tilfredsstiller BST tilstand.

d) Ved hjelp av dette, vil vi sjekke BST tilstand med gjeldende node. Og vi vil gjenta det samme til roten.

e) Fra hver node to gjenstander vil bli returnert. en for siste maksimal BST og en for strøm BST tilfredsstillende noder. Så fra hver node (ovenfor blad) (2 + 2) = 4 (2 til venstre subtre og 2 til høyre undertreet) objekter vil bli sammenlignet, og to vil bli returnert.

f) Den endelige maksimale node objekt fra roten vil være det største BST

PROBLEM:

Det er et problem i denne tilnærmingen. Mens du følger denne tilnærmingen, hvis en deltre ikke er tilfredsstillende BST tilstand med gjeldende node, vi kan ikke bare ignorere treet (selv om den har mindre antall noder). For eksempel

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

Fra bladnodene (20,110) blir objektene testet med node (105), tilfredsstiller den betingelse. Men når det kommer til node (95) bladnoden (20) tilfredsstiller ikke BST tilstand. Ettersom denne løsningen er for BST (ikke-indusert) skal vi ikke se bort fra node (105) og node (110), som tilfredsstiller betingelsen. Så fra node (95) vi har tilbake igjen testing BST tilstand og fange de noder (105, 110).

Den komplette koden for denne implementeringen er tilgjengelig på denne linken

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

Svarte 26/03/2014 kl. 23:48
kilden bruker

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