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