Κατά τη διαγραφή ενός κόμβου με δύο παιδιά, μπορείτε είτε να επιλέξετε διάδοχος στην παραγγελία κόμβο του ή σε σειρά κόμβο προκάτοχό του. Σε αυτή την περίπτωση είναι να βρεθεί η η μεγαλύτερη τιμή στο αριστερό υπο-δέντρο (που σημαίνει το δικαίωμα-τα περισσότερα παιδί του αριστερού υπο-δέντρο), το οποίο σημαίνει ότι είναι η εξεύρεση στην παραγγελία κόμβο του προκατόχου του κόμβου.
Μόλις βρείτε τον κόμβο αντικατάστασης, που στην πραγματικότητα δεν διαγράψετε τον κόμβο που θέλετε να διαγράψετε. Αντί να πάρετε την τιμή από τον διάδοχο κόμβο και να αποθηκεύσετε την τιμή αυτή στον κόμβο που θέλετε να διαγράψετε. Στη συνέχεια, μπορείτε να διαγράψετε το διάδοχο κόμβο. Με αυτό τον τρόπο θα διατηρηθεί η δυαδική ιδιότητα αναζήτησης δέντρο δεδομένου ότι μπορείτε να είστε σίγουροι ότι ο κόμβος που επιλέξατε θα έχει μια τιμή που είναι χαμηλότερη από τις τιμές όλων των παιδιών στο αριστερό υπο-δέντρο του αρχικού κόμβου και μεγαλύτερη ότι από τις τιμές όλων των παιδιών στη σωστή υπο-δέντρο του αρχικού κόμβου.
ΕΠΕΞΕΡΓΑΣΙΑ
Μετά την ανάγνωση ερώτησή σας λίγο περισσότερο, νομίζω ότι έχουν βρει το πρόβλημα.
Συνήθως αυτό που έχετε εκτός από την 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