De ce-mi cod C ++ nu pentru a șterge toate nodurile din BST mea?

voturi
1

Acest lucru ar trebui să traverseze o BST și șterge fiecare nod, inclusiv nodul rădăcină. Cu toate acestea, la sfârșitul anului, am primit mesajul „rădăcină are încă un nod stânga.“ De ce nu sunt toate nodurile șterse?

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;
}   
Întrebat 11/02/2010 la 03:57
sursa de către utilizator
În alte limbi...                            


5 răspunsuri

voturi
6

Dvs. sunt ștergerea pla sfârșitul anului ( root) și apoi încearcă să acceseze conținutul său în deleteTree(), în cazul în care rootnu mai puncte în memoria alocată. Rezultatul va fi nedefinită.

Publicat 11/02/2010 la 04:00
sursa de către utilizator

voturi
2

Că ștergeți root. Și apoi codul dvs. încearcă să acceseze memoria unde era.

Ești bine în teren nedefinită-comportament acolo.

Publicat 11/02/2010 la 04:01
sursa de către utilizator

voturi
2

Nu ar trebui să endiancu rootdupă ce îl ștergeți în deleteNode. Utilizați un program de depanare pentru a inspecta de ce root->lefteste non-nul.

Publicat 11/02/2010 la 04:01
sursa de către utilizator

voturi
2

Te uiți la root->leftrădăcină , după ce ați șters deja, făcându - l avalable pentru utilizare într - un bloc nou alocat.

Publicat 11/02/2010 la 04:02
sursa de către utilizator

voturi
-1

Mi-ar schimba pur și simplu copacul în sine, ar fi mai ușor să se ocupe de ea, atunci:

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

Fiind Orientate-obiect, fiecare nod este acum responsabil pentru memoria se ocupă. De asemenea, folosind std::auto_ptrîn interfața arată clar că este nevoie de proprietate.

Rețineți că acesta a fost adaptat pentru deep-copiere, orice altă abordare care necesită boost::shared_ptrsau echivalent. Și da , std::auto_ptrte lasă face cu copierea de unul singur, nici o magie acolo.

Acest design este mult mai curat decât cu ajutorul unui simplu C-structcu toată lumea fiind capabil de a manipula resursele. Încă mai avea acces deplin la datele care stau la baza prin intermediul accessor ... dar ei avea grijă să nu invoce un comportament nedefinit ...

Desigur, puteți totuși crash jos:

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

Dar dacă C ++ poate proteja împotriva probleme neintenționate, lasă ușa deschisă la codul rău.

Publicat 11/02/2010 la 14:22
sursa de către utilizator

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