Eliminare in Binary Search albero?

voti
0

Sto leggendo attraverso l'albero binario eliminare algoritmo nodo utilizzato nel libro algoritmi e strutture dati: Riferimento commentata con esempi

a pagina 34, caso 4 (Elimina nodo che ha entrambi gli alberi sotto a destra ea sinistra), seguente algoritmo descritto nel libro sembra non funziona, probabilmente posso sbagliarmi qualcuno potrebbe aiutarmi cosa che mi manca.

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

Come funziona la seguente riga cancella il valore più grande da un albero sub FindParent(largestValue).Right <- 0

È pubblicato 29/06/2010 alle 21:09
fonte dall'utente
In altre lingue...                            


5 risposte

voti
1

L'idea è di prendere semplicemente il valore del più grande nodo sulla sinistra e spostarlo al nodo che viene cancellato, vale a dire, non eliminare il nodo a tutti, basta sostituire il suo contenuto. Poi potare il nodo con il valore si è spostato nel nodo "cancellato". Questo mantiene l'ordinamento albero con il valore di ogni nodo più grande di tutti è lasciato i bambini e più piccolo di tutto questo per i bambini giusti.

Risposto il 29/06/2010 a 21:16
fonte dall'utente

voti
1

Se ho ben capito il pseudo-codice, funziona nel caso generale, ma non riesce a "un nodo nella sinistra sottostruttura" caso. Bella presa.

Esso sostituisce efficacemente il node_to_remove con largest_value dal suo sottoalbero sinistro (NULLS anche il vecchio nodo largest_value).

Si noti che in un BST, il sottoalbero sinistro di node_to_remove sarà tutto essere inferiore a node_to_remove. Il diritto di sotto-albero node_to_remove saranno tutti più grandi di node_to_remove. Quindi, se si prende il nodo più grande nella sottostruttura sinistra, può conservare l'invariante.

Se questo è un "un nodo nel caso sottostruttura", sarà distruggere invece il sottoalbero destro. Noioso :(

Come Vivin sottolinea, non riesce anche per riattaccare i bambini di sinistra del largestNode.

Risposto il 29/06/2010 a 21:16
fonte dall'utente

voti
6

Quando si elimina un nodo con due figli, è possibile scegliere il suo nodo in ordine successore o il suo in-ordine nodo predecessore. In questo caso è trovare il valore più grande nel sotto-albero a sinistra (nel senso che il bambino più a destra del suo sinistro sotto-albero), il che significa che sta trovando in ordine nodo predecessore del nodo.

Una volta trovato il nodo sostitutivo, in realtà non cancella il nodo da cancellare. Invece si prende il valore dal nodo successore e memorizzare tale valore nel nodo che si desidera eliminare. Poi, si elimina il nodo successore. In tal modo a conservare la proprietà di ricerca-albero binario dal momento che si può essere sicuri che il nodo selezionato avrà un valore che è inferiore ai valori di tutti i bambini della sinistra sub-albero del nodo originale, e una maggiore che rispetto ai valori di tutti i bambini a destra sotto-albero del nodo originale.

MODIFICARE

Dopo aver letto la tua domanda un po 'più, credo di aver trovato il problema.

In genere ciò che avete in aggiunta alla deletefunzione è una replacefunzione che sostituisce il nodo in questione. Penso che è necessario modificare questa riga di codice:

FindParent(largestValue).Right <- 0

a:

FindParent(largestValue).Right <- largestValue.Left

Se il largestValuenodo non ha un figlio sinistro, è sufficiente ottenere nullo 0. Se non avere un figlio a sinistra, quel bambino diventa un sostituto per il largestValuenodo. Quindi hai ragione; il codice non prende in considerazione lo scenario che il largestValuenodo potrebbe avere un figlio sinistro.

Un altro EDIT

Dal momento che hai postato solo un frammento, non sono sicuro di quello che il contesto del codice è. Ma il frammento come pubblicato sembra avere il problema suggerisci (che sostituisce il nodo sbagliato). Di solito, ci sono tre casi, ma noto che il commento nel vostro frammento dice //Case 4(così forse c'è qualche altro contesto).

In precedenza, ho accennato al fatto che deletedi solito viene fornito con una replace. Quindi, se si trova il largestValuenodo, lo si elimina secondo i due casi semplici (nodo senza figli, e il nodo con un bambino). Quindi, se stai guardando pseudo-codice per eliminare un nodo con due figli, questo è ciò che farete:

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

Trovo strano che uno Strutture Dati e algoritmi libro sarebbe lasciare fuori questa parte, quindi sono propenso a pensare che il libro ha ulteriormente dividere la cancellazione in un paio di casi (dato che ci sono tre casi standard) per rendere più facile capire.

Per dimostrare che il codice precedente funziona, si consideri il seguente albero:

  8
 / \
7   9

Diciamo che si desidera eliminare 8. Si tenta di trovare largestValueda nodeToRemove.Left. Questo ti dà 7in quanto il sub-struttura a sinistra ha un solo figlio.

Poi si fa:

nodeToRemove.Value <- largestValue.Value

Che significa:

8.value <- 7.Value

o

8.Value <- 7

Così ora il vostro albero assomiglia a questo:

  7
 / \
7   9

È necessario sbarazzarsi del nodo di sostituzione e così si sta andando a sostituire largestValuecon largestValue.Left(che è null). Quindi, prima di scoprire che tipo di bambino 7è:

if largestValue = largestValue.Parent.Left then

Che significa:

if 7 = 7.Parent.Left then

o:

if 7 = 8.Left then

Dal momento che 7non è in 8figlio sinistro s', necessario sostituire 8.Leftcon 7.Right( largestValue.Parent.Left <- largestValue.Left). Dal momento che 7non ha figli, 7.Leftè nullo. Quindi, largestValue.Parent.Leftviene assegnato a null (che rimuove efficacemente il suo figlio sinistro). Quindi questo significa che si finisce con la seguente struttura:

  7
   \
    9
Risposto il 29/06/2010 a 21:17
fonte dall'utente

voti
0

Si può rendere più senso quando si guarda al di Wikipedia assumere tale parte dell'algoritmo:

L'eliminazione di un nodo con due figli : Chiamare il nodo da cancellare "N". Non eliminare N. Invece, scegliere il suo nodo successore in ordine o la sua in-order nodo predecessore, "R". Sostituire il valore di N con il valore di R, quindi eliminare R. (Nota: R si ha fino a un bambino.)

Si noti che il dato algoritmo sceglie il nodo predecessore in ordine.

Edit: ciò che sembra mancare la possibilità che R (per usare la terminologia di Wikipedia) ha un figlio. Una cancellazione ricorsiva potrebbe funzionare meglio.

Risposto il 29/06/2010 a 21:20
fonte dall'utente

voti
1

Penso che potrebbe essere necessario per chiarire che cosa non funziona.

Cercherò di spiegare il concetto di delezione in un albero binario nel caso in cui questo aiuta.

Lascia supporre che si dispone di un nodo nell'albero che ha due nodi figlio che si desidera eliminare. nell'albero sotto Diciamo che si desidera eliminare Nodo B
           un
         / \
       b c
     / \ / \
   d e f g

Quando cancelliamo un nodo che dobbiamo riattaccare i suoi nodi dipendenti.

vale a dire. Quando cancelliamo B abbiamo bisogno di ricollegare i nodi d ed e.

Sappiamo che i nodi di sinistra sono meno i nodi giusti, in valore e che i nodi principali sono tra il nodo destra e sinistra s di valore. In questo caso d <b and b <e. Questa è parte della definizione di un albero binario.

Quello che è un po 'meno ovvio è che l'e <a. Quindi questo significa che possiamo sostituire b con e. Ora abbiamo riattaccato e abbiamo bisogno di ricollegare d.

Come detto prima d <e in modo da poter collegare e come nodo di sinistra e.

La cancellazione è ora completa.

(Btw Il processo di spostamento di un nodo l'albero e ridisporre i nodi dipendenti in questo modo è noto come promozione di un nodo. È inoltre possibile promuovere un nodo senza eliminare altri nodi.)


           un
         / \
       d c
         \ / \
          e f g

Si noti che esiste un altro risultato perfettamente legittimo deleteing nodo b. Se abbiamo scelto di promuovere il nodo D al posto del nodo e l'albero sarebbe simile a questa.


           un
         / \
       e C
     / / \
   d f g

Risposto il 29/06/2010 a 21:44
fonte dall'utente

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