Supprimer dans l'arbre de recherche binaire?

voix
0

Je lis à travers l'arbre binaire supprimer algorithme de nœud utilisé dans le livre Structures de données et algorithmes: Référence annotés avec exemples

à la page 34, case 4 (Supprimer le noeud qui a deux sous-arbres à droite et à gauche), algorithme suivant décrit dans le livre semble ne fonctionne pas, sans doute, je peux me tromper quelqu'un pourrait me aider ce que je suis absent.

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

Comment la ligne suivante supprime la plus grande valeur de l'arbre sous FindParent(largestValue).Right <- 0

Créé 29/06/2010 à 21:09
source utilisateur
Dans d'autres langues...                            


5 réponses

voix
1

L'idée est de prendre simplement la valeur du nœud le plus grand sur le côté gauche et le déplacer vers le noeud qui est en cours de suppression, par exemple, ne supprimez pas le nœud du tout, il suffit de remplacer son contenu. Ensuite, vous taillez le nœud avec la valeur que vous avez déplacé dans le noeud « supprimé ». Cela permet de maintenir l'ordre d'arbre avec la valeur de chaque nœud plus grand que tout cela qui reste des enfants et plus petit que l'ensemble de ses enfants droit.

Créé 29/06/2010 à 21:16
source utilisateur

voix
1

Si je comprends le pseudo-code, cela fonctionne dans le cas général, mais échoue dans le « un nœud dans le sous-arbre gauche » cas. Belle prise.

Il remplace efficacement le node_to_remove avec largest_value à partir de son sous-arbre gauche (NULLS aussi l'ancien noeud de largest_value).

Notez que dans un BST, le sous-arbre gauche de node_to_remove sera tout plus petit que node_to_remove. Le sous-arbre droit de node_to_remove tout sera plus grand que node_to_remove. Donc, si vous prenez le plus grand nœud dans la sous-arborescence à gauche, il conservera l'invariant.

Si cela est un « un nœud dans le cas de sous-arbre », il va détruire le sous-arbre droit à la place. :( boiteuse

Comme Vivin souligne, il omet également de remettre en place les enfants de gauche largestNode.

Créé 29/06/2010 à 21:16
source utilisateur

voix
6

Lors de la suppression d'un nœud avec deux enfants, vous pouvez choisir son noeud successeur d'ordre ou son dans l'ordre noeud prédécesseur. Dans ce cas, il est de trouver la valeur la plus élevée dans le sous-arbre gauche (ce qui signifie le droit enfant le plus de son sous-arbre gauche), ce qui signifie qu'il est de trouver dans l'ordre nœud prédécesseur du nœud.

Une fois que vous trouvez le nœud de remplacement, vous ne pas réellement supprimer le nœud à supprimer. Au lieu de cela , vous prenez la valeur du nœud successeur et de stocker cette valeur dans le nœud que vous souhaitez supprimer. Ensuite, vous supprimez le nœud successeur. Ce faisant, vous préservez la propriété binaire recherche d'arbres puisque vous pouvez être sûr que le nœud sélectionné aura une valeur qui est inférieure aux valeurs de tous les enfants sous-arbre gauche du noeud d' origine, et plus que que les valeurs de tous les enfants dans le droit du nœud d' origine sous-arbre.

MODIFIER

Après avoir lu votre question un peu plus, je crois avoir trouvé le problème.

En général ce que vous avez en plus de la deletefonction est une replacefonction qui remplace le nœud en question. Je pense que vous devez changer cette ligne de code:

FindParent(largestValue).Right <- 0

à:

FindParent(largestValue).Right <- largestValue.Left

Si le largestValuenœud ne dispose pas d' un enfant à gauche, vous simplement obtenir nullou 0. Si elle a un enfant laissé, cet enfant devient un remplacement pour le largestValuenœud. Donc , vous avez raison; le code ne prend pas en compte le scénario que le largestValuenœud peut avoir un enfant gauche.

une autre EDIT

Puisque vous avez seulement posté un extrait, je ne suis pas sûr de ce que le contexte du code est. Mais l'extrait comme affiché ne semble pas avoir le problème que vous proposez (remplacer le mauvais nœud). En général, il y a trois cas, mais je remarque que le commentaire dans votre extrait dit //Case 4(alors peut - être il y a un autre contexte).

Plus tôt, je faisais allusion au fait que deletevient habituellement avec replace. Donc , si vous trouvez le largestValuenœud, vous le supprimez selon les deux cas simples (noeud sans enfant, et le noeud avec un enfant). Donc , si vous cherchez à pseudo-code pour supprimer un nœud avec deux enfants, c'est ce que vous allez faire:

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

Je trouve étrange qu'un Structures de données et livre Les algorithmes quitteraient cette partie, donc je suis enclin à penser que le livre a encore divisé la suppression dans quelques autres cas (car il y a trois cas standards) pour le rendre plus facile à comprendre.

Pour prouver que le code ci-dessus fonctionne, considérez l'arbre suivant:

  8
 / \
7   9

Disons que vous voulez supprimer 8. Vous essayez de trouver largestValuede nodeToRemove.Left. Cela vous donne 7depuis le sous-arbre gauche n'a qu'un seul enfant.

Ensuite, vous faites:

nodeToRemove.Value <- largestValue.Value

Ce qui signifie:

8.value <- 7.Value

ou

8.Value <- 7

Alors maintenant votre arbre ressemble à ceci:

  7
 / \
7   9

Vous devez vous débarrasser du nœud de remplacement et donc vous allez remplacer largestValuepar largestValue.Left( ce qui est null). Alors d' abord vous trouvez ce genre d'enfant 7est:

if largestValue = largestValue.Parent.Left then

Ce qui signifie:

if 7 = 7.Parent.Left then

ou:

if 7 = 8.Left then

Depuis 7est -à- 8enfant gauche de l », besoin de remplacer 8.Leftpar 7.Right( largestValue.Parent.Left <- largestValue.Left). Depuis 7n'a pas d' enfant, 7.Leftest nulle. Alors largestValue.Parent.Leftobtient attribué à null (qui élimine efficacement son enfant à gauche). Cela signifie donc que vous vous retrouvez avec l'arbre ci - dessous:

  7
   \
    9
Créé 29/06/2010 à 21:17
source utilisateur

voix
0

Il peut être plus judicieux quand vous regardez le Wikipedia de prendre sur cette partie de l'algorithme:

La suppression d' un nœud avec deux enfants : Appelez le nœud à supprimer « N ». Ne supprimez pas N. Au lieu de cela, choisissez son noeud successeur dans l'ordre ou son dans l'ordre noeud prédécesseur, « R ». Remplacez la valeur de N avec la valeur de R, puis supprimez R. (Note: R a lui - même jusqu'à un enfant.)

Notez que l'algorithme donné choisit le noeud dans l'ordre précédent.

Edit: ce qui semble manquer la possibilité que R (pour utiliser la terminologie de Wikipedia) a un enfant. Un effacement récursif pourrait mieux fonctionner.

Créé 29/06/2010 à 21:20
source utilisateur

voix
1

Je pense que vous devrez peut-être clarifier ce qui ne fonctionne pas.

Je vais essayer d'expliquer le concept de suppression dans un arbre binaire dans le cas où cette aide.

Supposons aussi que vous avez un nœud dans l'arbre qui a deux nœuds enfants que vous souhaitez supprimer. dans l'arbre ci - dessous que vous permet de dire à supprimer le noeud b
           a
         / \
       b c
     / \ / \
   d e f g

Lorsque l'on supprime un nœud que nous devons remettre en place ses nœuds dépendants.

c'est à dire. Lorsque nous supprimons b nous devons remettre en place les nœuds d et e.

Nous savons que les nœuds de gauche sont inférieurs aux noeuds de droite de la valeur et que les nœuds parents sont entre le noeud gauche et à droite de de la valeur. Dans ce cas, d <b et b <e. Cela fait partie de la définition d'un arbre binaire.

Ce qui est un peu moins évidente est que e <a. Donc, cela signifie que nous pouvons remplacer b avec e. Maintenant, nous avons recollé e que nous devons remettre en place d.

Comme indiqué précédemment d <e afin que nous puissions joindre e en tant que nœud de gauche e.

La suppression est maintenant terminée.

(BTW Le processus de déplacement d'un nœud en place Vous pouvez également promouvoir un nœud sans supprimer d'autres nœuds de l'arbre et réorganisant les nœuds dépendants de cette manière est connue comme la promotion d'un nœud.).


           un
         / \
       d c
         \ / \
          e f g

Notez qu'il existe un autre résultat tout à fait légitime du noeud deleteing b. Si nous avons choisi de promouvoir le noeud d e au lieu de nœud de l'arbre ressemblerait à ceci.


           un
         / \
       e c
     / / \
   d f g

Créé 29/06/2010 à 21:44
source utilisateur

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