Slett i binært søketre?

stemmer
0

Jeg leser gjennom det binære treet slette node algoritmen som brukes i boken Datastrukturer og Algoritmer: Annotated Reference med eksempler

på side 34, sak 4 (Slett node som har både høyre og venstre sub trær), følgende algoritme beskrevet i boken ser ikke fungerer, sannsynligvis jeg kan være galt kan noen hjelpe meg hva jeg mangler.

//Case 4
get largestValue from nodeToRemove.Left
FindParent(largestValue).Right <- 0
nodeToRemove.Value<-largestValue.Value

Hvordan til følgende linje sletter den største verdien fra sub treet FindParent(largestValue).Right <- 0

Publisert på 29/06/2010 klokken 20:09
kilden bruker
På andre språk...                            


5 svar

stemmer
1

Ideen er å bare ta verdien fra den største node på venstre side og flytte den til noden som blir slettet, dvs. ikke slette noden i det hele tatt, bare erstatte det er innholdet. Deretter kan du beskjære ut noden med verdien du flyttet inn i "slettet" node. Dette opprettholder treet bestilling med hver node verdi større enn alt det som er igjen barn og mindre enn alt det riktige barn.

Svarte 29/06/2010 kl. 20:16
kilden bruker

stemmer
1

Hvis jeg forstår pseudo-kode, det fungerer i det generelle tilfellet, men klarte ikke i "en node i venstre subtre" case. Bra tatt i mot.

Den erstatter effektivt node_to_remove med largest_value fra det venstre subtre (også nuller den gamle largest_value node).

Merk at i en BST, vil venstre subtre av node_to_remove være alt være mindre enn node_to_remove. Retten undertreet av node_to_remove vil alle være større enn node_to_remove. Så hvis du tar den største node i venstre undertreet, vil det bevare invariant.

Hvis dette er en "en node i treet case", vil det ødelegge den rette treet i stedet. Lame :(

Som Vivin påpeker, klarer den også å feste venstre barn largestNode.

Svarte 29/06/2010 kl. 20:16
kilden bruker

stemmer
6

Når du sletter en node med to barn, kan du enten velge sin i-order etterfølger node eller sin i-order forgjenger node. I dette tilfellet er det å finne den største verdien i venstre sub-treet (som betyr lengst til høyre barn av sin venstre sub-treet), noe som betyr at det er å finne noden er i bestilling forgjenger node.

Når du finner den nye noden, trenger du faktisk ikke slette noden som skal slettes. I stedet du tar verdien fra etterfølgeren node og lagre verdien i noden du vil slette. Deretter sletter du etterfølg node. Ved å gjøre det du bevare det binære søketreet eiendom siden du kan være sikker på at noden du valgte vil ha en verdi som er lavere enn verdiene av alle barna i den opprinnelige noden venstre sub-treet, og større enn enn verdiene av alle barn i den opprinnelige noden rett sub-treet.

REDIGERE

Etter å ha lest spørsmålet ditt litt mer, jeg tror jeg har funnet problemet.

Vanligvis hva du har i tillegg til deletefunksjonen er en replacefunksjon som erstatter node i spørsmålet. Jeg tror du må endre denne linjen med kode:

FindParent(largestValue).Right <- 0

til:

FindParent(largestValue).Right <- largestValue.Left

Hvis largestValuenoden ikke har en venstre barn, du bare få nulleller 0. Hvis det har en forlatt barnet, blir barnet en erstatning for den largestValuenoden. Så du har rett; koden ikke tar hensyn til scenariet at largestValuenoden kan ha en venstre barn.

en annen EDIT

Siden du bare har lagt ut en bit, jeg er ikke sikker på hva sammenheng med koden. Men tekstutdraget som postet ser ut til å ha det problemet du foreslår (erstatte feil node). Vanligvis er det tre tilfeller, men jeg merker at kommentaren i tekstutdraget sier //Case 4(så kanskje det er noen annen sammenheng).

Tidligere antydet jeg til det faktum at deletevanligvis kommer med en replace. Så hvis du finner den largestValuenode, sletter du den i henhold til to enkle tilfeller (node uten barn, og node med ett barn). Så hvis du ser på pseudo-kode for å slette en node med to barn, er dette hva du vil gjøre:

get largestValue from nodeToRemove.Left
nodeToRemove.Value <- largestValue.Value

//now replace largestValue with largestValue.Left    

if largestValue = largestValue.Parent.Left then   
   largestValue.Parent.Left <- largestValue.Left //is largestValue a left child?
else //largestValue must be a right child
   largestValue.Parent.Right <- largestValue.Left

if largestValue.Left is not null then
   largestValue.Left.Parent <- largestValue.Parent

Jeg finner det underlig at en datastrukturer og algoritmer boken ville la ut denne delen, så jeg er tilbøyelig til å tro at boken har videre delt opp slettingen inn noen flere tilfeller (siden det er tre vanlige tilfeller) for å gjøre det enklere å forstå.

For å bevise at koden ovenfor fungerer, bør du vurdere følgende tre:

  8
 / \
7   9

La oss si at du ønsker å slette 8. Du prøver å finne largestValuefra nodeToRemove.Left. Dette gir deg 7da til venstre sub-tre bare har ett barn.

Deretter gjør du:

nodeToRemove.Value <- largestValue.Value

Som betyr:

8.value <- 7.Value

eller

8.Value <- 7

Så nå treet ser slik ut:

  7
 / \
7   9

Du trenger å bli kvitt den nye noden og så kommer du til å erstatte largestValuemed largestValue.Left(som er null). Så først finne ut hva slags barn 7er:

if largestValue = largestValue.Parent.Left then

Som betyr:

if 7 = 7.Parent.Left then

eller:

if 7 = 8.Left then

Siden 7vil si 8er igjen barnet, må erstatte 8.Leftmed 7.Right( largestValue.Parent.Left <- largestValue.Left). Siden 7har ingen barn, 7.Lefter null. Så largestValue.Parent.Leftblir fordelt til null (som effektivt fjerner sin venstre barn). Så dette betyr at du ender opp med følgende tre:

  7
   \
    9
Svarte 29/06/2010 kl. 20:17
kilden bruker

stemmer
0

Det kan være mer fornuftig når du ser på Wikipedias ta på den delen av algoritmen:

Slette en node med to barn : Ring noden som skal slettes "N". Ikke slett N. I stedet velger enten sin i-order etterfølger node eller sin i-order forgjenger node, "R". Erstatte verdien av N med verdien av R, deretter slette R. (Merk: R selv har opp til ett barn.)

Legg merke til at den gitte algoritmen velger i for forgjenger node.

Edit: det som ser ut til å mangle muligheten for at R (for å bruke Wikipedia terminologi) har ett barn. En rekursiv slette kan fungere bedre.

Svarte 29/06/2010 kl. 20:20
kilden bruker

stemmer
1

Jeg tror du kan trenge for å avklare hva som ikke virker.

Jeg vil prøve å forklare begrepet sletting i et binært tre i tilfelle dette hjelper.

La oss anta at du har en node i treet som har to barn noder som du ønsker å slette. i treet nedenfor kan si at du vil slette node b
           en
         / \
       b c
     / \ / \
   d e f g

Når vi sletter en node må vi feste sine avhengige noder.

dvs. Når vi sletter b må vi feste noder d og e.

Vi vet at de venstre noder er mindre enn de riktige noder i verdi og at de overordnede nodene er mellom venstre og høyre node s i verdi. I dette tilfellet d <b og b <e. Dette er en del av definisjonen av et binært tre.

Hva er litt mindre åpenbare er at e <a. Så dette betyr at vi kan erstatte b med e. Nå har vi reattached e vi trenger å feste d.

Som nevnt før d <e, slik at vi kan feste e som den venstre noden e.

Slettingen er nå fullført.

(Forresten Prosessen med å flytte en node opp treet og ordner de avhengige noder på denne måte er kjent som fremmer en node. Det kan også fremme en node uten å slette andre noder).


           en
         / \
       d c
         \ / \
          e f g

Legg merke til at det er en annen helt legitimt utfallet av du sletter node b. Hvis vi velger å fremme node d i stedet for node e treet ville se slik ut.


           en
         / \
       e c
     / / \
   d f g

Svarte 29/06/2010 kl. 20:44
kilden bruker

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