Ștergerea în binar copac de căutare?

voturi
0

Am citit prin arborele binar șterge algoritm nod folosit în carte Structuri de date și algoritmi: Referință adnotate cu exemple

la pagina 34, caz 4 (Ștergere nod care are atât copaci sub dreapta și stânga), urmând algoritmul descris în cartea pare nu funcționează, probabil că poate fi greșit ar putea cineva să mă ajute ceea ce am lipsesc.

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

Cum următoarea linie șterge cea mai mare valoare din copac sub- FindParent(largestValue).Right <- 0

Întrebat 29/06/2010 la 21:09
sursa de către utilizator
În alte limbi...                            


5 răspunsuri

voturi
1

Ideea este de a lua pur și simplu valoarea de la cel mai mare nod de pe partea stângă și mutați-l la nodul care se elimină, de exemplu, nu ștergeți nodul de la toate, trebuie doar să o înlocuiască e conținutul. Apoi le tăiați din nodul cu valoarea pe care ați mutat în nodul „șters“. Aceasta susține ordonarea arborelui cu valoarea fiecărui nod este mai mare decât toate este lăsat copiii și mai mici decât toate este de copii din dreapta.

Publicat 29/06/2010 la 21:16
sursa de către utilizator

voturi
1

Dacă am înțeles pseudo-cod, acesta funcționează în cazul general, dar eșuează în „un nod în subarborele stâng“ caz. Nisa de captură.

Acesta înlocuiește în mod eficient node_to_remove cu largest_value de la subramificație este stânga (NULLS, de asemenea, nodul largest_value vechi).

Rețineți că într-un BST, subarborele stâng al node_to_remove vor fi toate fi mai mică decât node_to_remove. Subarborele drept al node_to_remove va fi tot mai mare decât node_to_remove. Deci, dacă luați cel mai mare nod din subarborele din stânga, se va păstra invariantul.

În cazul în care acest lucru este un „un nod în cazul subramificație“, va distruge subarborelui drept loc. :( lame

După cum Vivin subliniază, de asemenea, nu reușește să atașați din nou copii stânga de largestNode.

Publicat 29/06/2010 la 21:16
sursa de către utilizator

voturi
6

La ștergerea unui nod cu doi copii, puteți alege fie nodul său în ordine succesorul sau nodul său în ordine predecesorul. În acest caz, este găsirea cea mai mare valoare din sub-arborele din stânga (adica copilul din dreapta-cele mai multe dintre sub-tree stânga), ceea ce înseamnă că este de a găsi în ordine nod predecesorul nodului.

Odată ce ați găsit nodul de înlocuire, de fapt , nu ștergeți nodul care urmează să fie șters. În schimb să luați valoarea din nodul succesor și se păstrează această valoare în nodul pe care doriți să -l ștergeți. Apoi, ștergeți nodul succesor. Procedând astfel încât să păstreze binar proprietatea de căutare copac , deoarece puteți fi siguri că nodul ați selectat va avea o valoare care este mai mică decât valorile tuturor copiilor din sub-arbore stânga nodului original, și o mai mare că decât valorile din toți copiii din sub-copac dreapta nodului original.

EDITAȚI | ×

Dupa ce a citit întrebarea dumneavoastră un pic mai mult, cred că am găsit problema.

De obicei ceea ce trebuie , în plus față de deletefuncția este o replacefuncție care să înlocuiască nodul în cauză. Cred că trebuie să modificați această linie de cod:

FindParent(largestValue).Right <- 0

la:

FindParent(largestValue).Right <- largestValue.Left

În cazul în care largestValuenodul nu are un copil stânga, pur și simplu te nullsau 0. În cazul în care are un copil plecat, acel copil devine un înlocuitor pentru largestValuenodul. Deci , ai dreptate; codul nu ia în considerare scenariul pe care largestValuenodul ar putea avea un copil stânga.

O altă EDIT

Din moment ce ai postat doar un fragment, eu nu sunt sigur ce este contextul codului. Dar fragmentul postat ca pare sa nu aiba problema sugerezi (înlocuind nodul greșit). De obicei, există trei cazuri, dar am observat că comentariul din fragmentul spune //Case 4(așa că poate exista un alt context).

Anterior, am făcut aluzie la faptul că , de deleteobicei , vine cu o replace. Deci , dacă găsiți largestValuenodul, îl ștergeți în conformitate cu cele două cazuri simple (nodul fara copii, si nodul cu un copil). Deci , dacă sunteți în căutarea la pseudo-cod pentru a șterge un nod cu doi copii, acest lucru este ceea ce veți face:

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

Mi se pare ciudat că un structuri de date și cartea Algoritmi ar lăsa această parte, așa că eu sunt înclinat să cred că cartea are în continuare împărțită eliminarea în câteva cazuri (din moment ce există trei cazuri în standard) pentru a face mai ușor de a intelege.

Pentru a dovedi că codul de mai sus funcționează, luați în considerare următorul copac:

  8
 / \
7   9

Să presupunem că doriți să -l ștergeți 8. Încercați să găsiți de largestValuela nodeToRemove.Left. Acest lucru vă oferă , 7deoarece sub-arborele stâng are doar un singur copil.

Apoi faci:

nodeToRemove.Value <- largestValue.Value

Care înseamnă:

8.value <- 7.Value

sau

8.Value <- 7

Deci, acum copacul arata ca acest lucru:

  7
 / \
7   9

Ai nevoie pentru a scăpa de nodul de înlocuire și așa vei înlocui largestValuecu largestValue.Left(care este null). Deci , mai întâi să aflați ce fel de copil 7este:

if largestValue = largestValue.Parent.Left then

Care înseamnă:

if 7 = 7.Parent.Left then

sau:

if 7 = 8.Left then

Din moment ce 7este 8copilul din stânga „s, trebuie să -l înlocuiască 8.Leftcu 7.Right( largestValue.Parent.Left <- largestValue.Left). Din moment ce 7nu are copii, 7.Lefteste nul. Deci , largestValue.Parent.Leftse atribuie null (care elimină în mod eficient copilul său din stânga). Deci , acest lucru înseamnă că va termina cu următorul copac:

  7
   \
    9
Publicat 29/06/2010 la 21:17
sursa de către utilizator

voturi
0

Se poate face mai mult sens atunci când te uiți la Wikipedia ia de pe acea parte a algoritmului:

Ștergerea unui nod cu doi copii : Apelați nodul care urmează să fie șters „N“. Nu ștergeți N. În schimb, pentru a alege fie în ordine nodul său succesorul sau nodul său în ordine predecesorul, „R“. Înlocuiți valoarea N cu valoarea lui R, apoi ștergeți R. (Notă: R în sine are până la un copil.)

Rețineți că algoritmul dat alege nodul predecesorul în ordine.

Editare: ceea ce pare a fi lipsește posibilitatea ca R (pentru a folosi terminologia Wikipedia) are un copil. O ștergere recursiv ar putea să funcționeze mai bine.

Publicat 29/06/2010 la 21:20
sursa de către utilizator

voturi
1

Cred că ar putea fi necesar să se clarifice ce nu funcționează.

Voi încerca și să explice conceptul de ștergere într-un arbore binar, în cazul în care acest lucru ajută.

Să presupunem că aveți un nod din arbore care are două noduri copil pe care doriți să le ștergeți. în arborele de mai jos vă permite să spun că doriți să ștergeți nodul b
           a
         / \
       b c
     / \ / \
   d e f g

Când vom șterge un nod trebuie să atașați din nou nodurile sale dependente.

adică. Când ștergem b trebuie să reatașați nodurile d și e.

Știm că nodurile stânga sunt mai mici decât nodurile corecte în valoare și că nodurile părinte sunt între nodul stânga și dreapta lui în valoare. În acest caz, d <b și b <e. Aceasta este o parte din definiția unui arbore binar.

Ceea ce este mai puțin evident este faptul că e <a. Deci, acest lucru înseamnă că putem înlocui b cu e. Acum am reatașat e avem nevoie pentru a reatasa d.

Așa cum sa menționat mai înainte d <e astfel încât să putem atașa e ca nodul stâng al e.

Eliminarea este acum completă.

(BTW procesul de mutare a unui nod în copac și rearanjarea nodurile dependente în acest mod este cunoscut ca promovarea unui nod. Puteți promova, de asemenea, un nod fără a șterge alte noduri.)


           a
         / \
       d c
         \ / \
          e f g

Rețineți că există un alt rezultat perfect legitim al nodului deleteing b. Dacă am ales să promoveze nodul d în loc de nod e copacul ar arata ca acest lucru.


           a
         / \
       e c
     / / \
   d f g

Publicat 29/06/2010 la 21:44
sursa de către utilizator

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