Διαγραφή σε δυαδική αναζήτηση δέντρο;

ψήφοι
0

Είμαι ανάγνωση μέσω του δυαδικού δένδρου διαγραφή αλγόριθμο κόμβου που χρησιμοποιείται στο βιβλίο Δομές Δεδομένων και Αλγόριθμοι: σχολιασμένη αναφοράς με παραδείγματα

στη σελίδα 34, περίπτωση 4 (Διαγραφή κόμβου που έχει τόσο δεξιά και αριστερά υπο δέντρα), μετά από αλγόριθμο που περιγράφεται στο βιβλίο φαίνεται δεν λειτουργεί, κατά πάσα πιθανότητα μπορεί να κάνω λάθος θα μπορούσε κάποιος να με βοηθήσει τι μου λείπει.

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

Πώς η ακόλουθη γραμμή διαγράφει τη μεγαλύτερη αξία από την υπο δέντρο FindParent(largestValue).Right <- 0

Δημοσιεύθηκε 29/06/2010 στις 21:09
πηγή χρήστη
Σε άλλες γλώσσες...                            


5 απαντήσεις

ψήφοι
1

Η ιδέα είναι να πάρετε απλά την τιμή από το μεγαλύτερο κόμβο στην αριστερή πλευρά και να το μετακινήσετε με τον κόμβο που έχει διαγραφεί, δηλαδή, δεν διαγράψετε τον κόμβο καθόλου, απλά αντικαταστήστε είναι το περιεχόμενο. Στη συνέχεια, μπορείτε να κλαδέψετε από τον κόμβο με την τιμή που μετακόμισε στο «διαγραφή» του κόμβου. Αυτό διατηρεί την παραγγελία δέντρο με την αξία του κάθε κόμβου μεγαλύτερο από όλα αυτά έχει απομείνει παιδιά και μικρότερα από ό, τι όλο αυτό είναι σωστό τα παιδιά.

Απαντήθηκε 29/06/2010 στις 21:16
πηγή χρήστη

ψήφοι
1

Αν καταλαβαίνω την ψευδο-κώδικα, λειτουργεί στη γενική περίπτωση, αλλά αποτυγχάνει στο «έναν κόμβο στο αριστερό υποδέντρο» υπόθεση. Νίκαια αλιευμάτων.

Αντικαθιστά αποτελεσματικά την node_to_remove με largest_value από το ότι είναι αριστερό υποδένδρο (μηδενικά και το παλιό κόμβο largest_value).

Σημειώστε ότι σε ένα BST, το αριστερό υποδένδρο του node_to_remove θα είναι όλα να είναι μικρότερο από node_to_remove. Το δικαίωμα υποδένδρο του node_to_remove όλα θα είναι μεγαλύτερη από ό, τι node_to_remove. Έτσι αν πάρετε το μεγαλύτερο κόμβο στο αριστερό υποδέντρο, θα διατηρηθεί η αμετάβλητες.

Εάν αυτό είναι ένα «έναν κόμβο στην περίπτωση υποδέντρο», αυτό θα καταστρέψει το δικαίωμα υποδένδρο αντ 'αυτού. Lame :(

Όπως Vivin επισημαίνει, αποτυγχάνει επίσης να ξαναβάλουν αριστερά τα παιδιά της largestNode.

Απαντήθηκε 29/06/2010 στις 21:16
πηγή χρήστη

ψήφοι
6

Κατά τη διαγραφή ενός κόμβου με δύο παιδιά, μπορείτε είτε να επιλέξετε διάδοχος στην παραγγελία κόμβο του ή σε σειρά κόμβο προκάτοχό του. Σε αυτή την περίπτωση είναι να βρεθεί η η μεγαλύτερη τιμή στο αριστερό υπο-δέντρο (που σημαίνει το δικαίωμα-τα περισσότερα παιδί του αριστερού υπο-δέντρο), το οποίο σημαίνει ότι είναι η εξεύρεση στην παραγγελία κόμβο του προκατόχου του κόμβου.

Μόλις βρείτε τον κόμβο αντικατάστασης, που στην πραγματικότητα δεν διαγράψετε τον κόμβο που θέλετε να διαγράψετε. Αντί να πάρετε την τιμή από τον διάδοχο κόμβο και να αποθηκεύσετε την τιμή αυτή στον κόμβο που θέλετε να διαγράψετε. Στη συνέχεια, μπορείτε να διαγράψετε το διάδοχο κόμβο. Με αυτό τον τρόπο θα διατηρηθεί η δυαδική ιδιότητα αναζήτησης δέντρο δεδομένου ότι μπορείτε να είστε σίγουροι ότι ο κόμβος που επιλέξατε θα έχει μια τιμή που είναι χαμηλότερη από τις τιμές όλων των παιδιών στο αριστερό υπο-δέντρο του αρχικού κόμβου και μεγαλύτερη ότι από τις τιμές όλων των παιδιών στη σωστή υπο-δέντρο του αρχικού κόμβου.

ΕΠΕΞΕΡΓΑΣΙΑ

Μετά την ανάγνωση ερώτησή σας λίγο περισσότερο, νομίζω ότι έχουν βρει το πρόβλημα.

Συνήθως αυτό που έχετε εκτός από την deleteλειτουργία είναι μια replaceλειτουργία που αντικαθιστά τον κόμβο εν λόγω. Νομίζω ότι θα πρέπει να αλλάξετε αυτή τη γραμμή κώδικα:

FindParent(largestValue).Right <- 0

προς το:

FindParent(largestValue).Right <- largestValue.Left

Αν ο largestValueκόμβος δεν έχει αριστερό παιδί, μπορείτε απλά να πάρετε nullή 0. Αν έχει μείνει το παιδί, το παιδί γίνεται μια αντικατάσταση για το largestValueκόμβο. Έτσι, έχεις δίκιο? ο κώδικας δεν λαμβάνει υπόψη το σενάριο που ο largestValueκόμβος μπορεί να έχει ένα αριστερό παιδί.

Μια άλλη EDIT

Από τη στιγμή που έχετε δημοσιεύσει μόνο ένα απόσπασμα, δεν είμαι σίγουρος ποιο είναι το πλαίσιο του κώδικα είναι. Αλλά το απόσπασμα, όπως δημοσιεύτηκε δεν φαίνεται να έχουν το πρόβλημα που προτείνουν (που αντικαθιστά το λάθος κόμβο). Συνήθως, υπάρχουν τρεις περιπτώσεις, αλλά παρατηρώ ότι το σχόλιο στο απόσπασμα λέει //Case 4(έτσι ίσως υπάρχει κάποιο άλλο πλαίσιο).

Νωρίτερα, αναφέρθηκα στο γεγονός ότι deleteσυνήθως έρχεται με ένα replace. Έτσι, αν βρείτε τον largestValueκόμβο, μπορείτε να το διαγράψετε, σύμφωνα με τις δύο απλές περιπτώσεις (κόμβος χωρίς παιδιά, και κόμβος με ένα παιδί). Έτσι, αν ψάχνετε σε ψευδο-κώδικα για να διαγράψετε έναν κόμβο με δύο παιδιά, αυτό είναι ό, τι θα κάνετε:

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

Θεωρώ ότι είναι περίεργο το γεγονός ότι ένα Δομές Δεδομένων και το βιβλίο Αλγόριθμοι θα αφήσει αυτό το μέρος, έτσι τείνω να πιστεύω ότι το βιβλίο έχει ακόμη διαχωριστεί η διαγραφή σε λίγες περισσότερες περιπτώσεις (δεδομένου ότι υπάρχουν τρεις τυπικές περιπτώσεις) ώστε να είναι πιο εύκολο να καταλαβαίνουν.

Για να αποδείξει ότι η παραπάνω κώδικα λειτουργεί, εξετάστε το ακόλουθο δέντρο:

  8
 / \
7   9

Ας πούμε ότι θέλετε να διαγράψετε 8. Θα προσπαθήσουμε να βρούμε largestValueαπό nodeToRemove.Left. Αυτό σας δίνει 7δεδομένου ότι το αριστερό υπο-δέντρο έχει μόνο ένα παιδί.

Στη συνέχεια, μπορείτε να κάνετε:

nodeToRemove.Value <- largestValue.Value

Που σημαίνει:

8.value <- 7.Value

ή

8.Value <- 7

Έτσι τώρα το δέντρο σας μοιάζει με αυτό:

  7
 / \
7   9

Θα πρέπει να απαλλαγούμε από τον κόμβο αντικατάστασης και έτσι θα πάμε να αντικαταστήσει largestValueμε largestValue.Left(που είναι null). Έτσι, πρώτα να μάθετε τι είδους παιδί 7είναι:

if largestValue = largestValue.Parent.Left then

Που σημαίνει:

if 7 = 7.Parent.Left then

ή:

if 7 = 8.Left then

Από 7Δηλαδή 8το αριστερό του παιδιού, πρέπει να αντικαταστήσετε 8.Leftμε 7.Right( largestValue.Parent.Left <- largestValue.Left). Δεδομένου ότι 7δεν έχει παιδιά, 7.Leftείναι μηδενική. Έτσι largestValue.Parent.Leftπαίρνει ανατεθεί σε null (το οποίο απομακρύνει αποτελεσματικά το αριστερό παιδί του). Έτσι, αυτό σημαίνει ότι θα καταλήξουμε με το ακόλουθο δέντρο:

  7
   \
    9
Απαντήθηκε 29/06/2010 στις 21:17
πηγή χρήστη

ψήφοι
0

Μπορεί να έχει περισσότερο νόημα, εάν κοιτάξει κανείς το Wikipedia το αναλάβει το τμήμα του αλγορίθμου:

Η διαγραφή ενός κόμβου με δύο παιδιά : Καλέστε τον κόμβο προς διαγραφή «Ν». Μην διαγράψετε Ν Αντ 'αυτού, επιλέγουν είτε σε σειρά κόμβο διάδοχό του ή σε σειρά κόμβο προκάτοχό του, «R». Αντικαταστήστε την τιμή του Ν με την τιμή του R, τότε διαγραφή R. (Σημείωση: η ίδια R έχει έως και ένα παιδί.)

Να σημειωθεί ότι η συγκεκριμένη αλγόριθμος επιλέγει τον κόμβο του προκατόχου στην παραγγελία.

Επεξεργασία: αυτό που φαίνεται να λείπει η πιθανότητα ότι R (για να χρησιμοποιήσουμε την ορολογία της Wikipedia) έχει ένα παιδί. Μια αναδρομική διαγραφή θα μπορούσε να λειτουργήσει καλύτερα.

Απαντήθηκε 29/06/2010 στις 21:20
πηγή χρήστη

ψήφοι
1

Νομίζω ότι μπορεί να χρειαστεί να διευκρινίσει τι δεν λειτουργεί.

Θα προσπαθήσω να εξηγήσω την έννοια της διαγραφής σε ένα δυαδικό δένδρο σε περίπτωση που αυτό βοηθά.

Ας υποθέσουμε ότι έχετε έναν κόμβο στο δέντρο που έχει δύο παιδιών κόμβους που θέλετε να διαγράψετε. στο δέντρο ας παρακάτω πούμε ότι θέλετε να διαγράψετε τον κόμβο β
           α
         / \
       β γ
     / \ / \
   δ ε στ ζ

Όταν διαγράφετε ένα κόμβο θα πρέπει να ξαναβάλουν εξαρτώνται από τους κόμβους της.

δηλ. Όταν διαγράφετε β θα πρέπει να ξαναβάλουν κόμβους δ και ε.

Γνωρίζουμε ότι τα αριστερά κόμβοι είναι μικρότερη από τα δεξιά κόμβους σε αξία και ότι οι μητρικές κόμβοι είναι μεταξύ της αξίας του αριστερού και του δεξιού κόμβο s. Σε αυτή την περίπτωση δ <β και β <ε. Αυτό είναι μέρος του ορισμού ενός δυαδικού δέντρου.

Τι είναι ελαφρώς λιγότερο προφανές είναι ότι ε <a. Έτσι, αυτό σημαίνει ότι μπορούμε να αντικαταστήσουμε β με το e. Τώρα έχουμε επανατοποθετηθεί e πρέπει να ξαναβάλουν d.

Όπως αναφέρθηκε πριν d <e, ώστε να μπορούμε να επισυνάψετε e ως αριστερό κόμβο της e.

Η διαγραφή είναι τώρα πλήρης.

(Btw Η διαδικασία μετακίνησης ενός κόμβου στο δέντρο και αναδιάταξη των κόμβων εξαρτάται από τον τρόπο αυτό που είναι γνωστό ως προώθηση ενός κόμβου. Μπορείτε επίσης να προωθήσει ένα κόμβο χωρίς να διαγράψετε άλλους κόμβους.)


           α
         / \
       ά c
         \ / \
          ε στ ζ

Σημειώστε ότι υπάρχει και μια άλλη απολύτως θεμιτό αποτέλεσμα της deleteing κόμβο b. Αν επιλέξαμε να προωθήσει κόμβο d αντί του κόμβου ε το δέντρο θα είναι κάπως έτσι.


           α
         / \
       e c
     / / \
   d f g

Απαντήθηκε 29/06/2010 στις 21:44
πηγή χρήστη

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