Hvorfor C ++ kode klarer å slette alle noder i min BST?

stemmer
1

Dette er ment å krysse en BST og slette hver node, inkludert rotnoden. Men på slutten, får jeg meldingen root fortsatt har en venstre node. Hvorfor er ikke alle noder slettet?

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;
}   
Publisert på 11/02/2010 klokken 02:57
kilden bruker
På andre språk...                            


5 svar

stemmer
6

Din sletter ppå slutten ( root) og deretter prøver å få tilgang til innholdet i deleteTree(), der rootikke lenger peker på allokert minne. Resultatet kommer til å bli definert.

Svarte 11/02/2010 kl. 03:00
kilden bruker

stemmer
2

Du sletter root. Og så koden din prøver å få tilgang til minnet hvor det var.

Du er godt inn udefinert-oppførsel land der.

Svarte 11/02/2010 kl. 03:01
kilden bruker

stemmer
2

Du bør ikke deferanseoperasjon rootetter at du har slettet den i deleteNode. Bruk en debugger for å inspisere hvorfor root->lefter ikke-null.

Svarte 11/02/2010 kl. 03:01
kilden bruker

stemmer
2

Du ser på root->leftetter at du allerede har slettet rot, noe som gjør det avalable for bruk i en ny tildelt blokk.

Svarte 11/02/2010 kl. 03:02
kilden bruker

stemmer
-1

Jeg ville bare endre selve treet, det ville være lettere å forholde seg til det da:

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;
};

Ved å være objektorientert, er hver node nå ansvarlig for minne den håndterer. Også bruker std::auto_ptri grensesnittet gjør det klart at det tar eierskap.

Legg merke til at det er blitt skreddersydd for dyp-kopiering, enhver annen tilnærming som krever boost::shared_ptreller tilsvarende. Og ja std::auto_ptrlater deg håndtere kopiering av deg selv, ingen magi der.

Dette designet er mye renere enn å bruke en vanlig C-structmed alle som er i stand til å manipulere ressursene. Du har fortsatt full tilgang til de underliggende data via laget ... men de tar seg ikke å påberope udefinert oppførsel ...

Selvfølgelig kan du fortsatt krasje det ned:

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

Men hvis C ++ kan beskytte mot utilsiktede problemer, det overlater døren åpen for onde kode.

Svarte 11/02/2010 kl. 13:22
kilden bruker

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