Γιατί η C μου κώδικα ++ αδυνατούν να διαγράψετε όλους τους κόμβους στη BST μου;

ψήφοι
1

Αυτό υποτίθεται ότι θα διασχίσει μια BST και να διαγράψει κάθε κόμβου, συμπεριλαμβανομένου του κόμβου ρίζας. Ωστόσο, στο τέλος, παίρνω το μήνυμα «ρίζα εξακολουθεί να έχει ένα αριστερό κόμβο.» Γιατί δεν διαγράφονται όλοι οι κόμβοι;

void deleteTree()
{   
    deleteNode(root);
    if(root->right)
        cout << root still has a right node << endl;
    if(root->left)
        cout << root still has a left node << endl;
    root = 0;

}   

void deleteNode(node *p) 
{   
    if(p->left) 
    {   
        deleteNode(p->left);
        p->left = 0;
    }   
    if(p->right) 
    {   
        deleteNode(p->right);
        p->right = 0;
    }   

    cout << Deleting node containing  << p->data << endl;
    delete p;
}   
Δημοσιεύθηκε 11/02/2010 στις 03:57
πηγή χρήστη
Σε άλλες γλώσσες...                            


5 απαντήσεις

ψήφοι
6

Σας διαγράφοντας pστο τέλος ( root) και, στη συνέχεια, προσπαθεί να αποκτήσει πρόσβαση το περιεχόμενό του στο deleteTree(), όπου rootδεν υπάρχουν πλέον σημεία για να διατεθεί μνήμης. Το αποτέλεσμα θα είναι απροσδιόριστο.

Απαντήθηκε 11/02/2010 στις 04:00
πηγή χρήστη

ψήφοι
2

Είσαι διαγραφή root. Και στη συνέχεια τον κωδικό σας προσπαθεί να αποκτήσει πρόσβαση μνήμης εκεί που ήταν.

Είσαι καλά σε απροσδιόριστο-συμπεριφορά γης εκεί.

Απαντήθηκε 11/02/2010 στις 04:01
πηγή χρήστη

ψήφοι
2

Δεν πρέπει να dereference rootαφού τη διαγράψετε το deleteNode. Χρησιμοποιήστε ένα πρόγραμμα εντοπισμού σφαλμάτων για να επιθεωρήσει γιατί root->leftείναι μη μηδενική.

Απαντήθηκε 11/02/2010 στις 04:01
πηγή χρήστη

ψήφοι
2

Έχετε μπροστά σας root->left, αφού έχετε ήδη διαγραφεί ρίζας, καθιστώντας avalable για χρήση σε μια νέα διατεθεί μπλοκ.

Απαντήθηκε 11/02/2010 στις 04:02
πηγή χρήστη

ψήφοι
-1

Θα αλλάξει απλά το ίδιο το δέντρο, θα ήταν πιο εύκολο να ασχοληθεί με το θέμα, στη συνέχεια:

struct Node
{
  Node(data_type data): mLeft(), mRight(), mData(data) {}
  Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
  {
    if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
    if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
  }
  Node& operator=(Node rhs)
  {
    this->swap(rhs);
    return *this;
  }
  ~Node() { }

  void swap(Node& rhs)
  {
    using std::swap;
    swap(mLeft, rhs.mLeft);
    swap(mRight, rhs.mRight);
    swap(mData, rhs.mData);
  }

  Node* left() const { return mLeft.get(); }
  void left(std::auto_ptr<Node> node) { mLeft= node; }

  Node* right() const { return mRight.get(); }
  void right(std::auto_ptr<Node> node) { mRight = node; }

  data_type& data() { return mData; }
  const data_type& data() const { return mData; }

private:
  std::auto_ptr<Node> mLeft;
  std::auto_ptr<Node> mRight;
  data_type mData;
};

Με το να είναι object-oriented, κάθε κόμβος είναι τώρα υπεύθυνη για τη μνήμη που χειρίζεται. Επίσης, χρησιμοποιώντας std::auto_ptrτο περιβάλλον εργασίας καθιστά σαφές ότι χρειάζεται ιδιοκτησίας.

Σημειώστε ότι είναι ήδη προσαρμοσμένο για βαθύ-αντιγραφή, οποιαδήποτε άλλη προσέγγιση που απαιτεί boost::shared_ptrή ισοδύναμο. Και ναι std::auto_ptrτα φύλλα σας που ασχολούνται με την αντιγραφή από τον εαυτό σας, δεν μαγεία εκεί.

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

Φυσικά, μπορείτε ακόμα να διακοπεί η λειτουργία κάτω:

Node& node = ...
delete node.left(); // haha

Αλλά αν C ++ μπορεί να προστατεύσει από ακούσια θέματα, αφήνει την πόρτα ανοιχτή στο κακό κώδικα.

Απαντήθηκε 11/02/2010 στις 14:22
πηγή χρήστη

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