Warum funktioniert mein C ++ Code nicht alle Knoten in meinem BST löschen?

stimmen
1

Dies soll ein BST zu durchlaufen und jeden Knoten, einschließlich der Root-Knoten löschen. Doch am Ende, bekomme ich die Meldung „root noch einen linken Knoten hat.“ Warum sind nicht alle Knoten gelöscht?

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;
}   
Veröffentlicht am 11/02/2010 um 03:57
quelle vom benutzer
In anderen Sprachen...                            


5 antworten

stimmen
6

Sie löschen pam Ende ( root) und dann zu versuchen , um seinen Inhalt in zuzugreifen deleteTree(), wo rootnicht mehr auf zugewiesenen Speicher. Das Ergebnis wird zu undefiniert.

Beantwortet am 11/02/2010 um 04:00
quelle vom benutzer

stimmen
2

Sie sind zu löschen root. Und dann der Code versucht , auf Speicher zuzugreifen , wo es war.

Sie sind gut in undefined-Verhalten Land gibt.

Beantwortet am 11/02/2010 um 04:01
quelle vom benutzer

stimmen
2

Sie sollten nicht dereferenzieren , rootnachdem Sie es in löschen deleteNode. Verwenden Sie einen Debugger zu untersuchen , warum root->leftnicht null ist .

Beantwortet am 11/02/2010 um 04:01
quelle vom benutzer

stimmen
2

Sie betrachten , root->leftnachdem Sie bereits gelöscht Wurzel haben, ist es für die Verwendung in einem neuen Block zugeordnet avalable machen.

Beantwortet am 11/02/2010 um 04:02
quelle vom benutzer

stimmen
-1

Ich würde einfach den Baum selbst ändern, wäre es einfacher, damit umzugehen, dann:

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

Durch die objektorientierte, ist jeder Knoten nun verantwortlich für die Speicher es abwickelt. Auch die Verwendung std::auto_ptrin der Schnittstelle macht deutlich , dass es Eigentum nimmt.

Beachten Sie, dass es für Tief Kopieren zugeschnitten worden ist, anderer Ansatz erfordern boost::shared_ptroder gleichwertig. Und ja std::auto_ptrläßt Sie selbst mit dem Kopieren zu tun, es gibt keine Magie.

Dieser Entwurf ist viel sauberer als mit einer Ebene C-structmit allen , die Ressourcen manipulieren zu können. Sie haben noch vollen Zugriff auf die zugrunde liegenden Daten über die Accessor ... aber sie kümmern sich nicht undefiniert Verhalten aufzurufen ...

Natürlich kann man es immer noch abstürzen:

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

Aber wenn C ++ gegen unbeabsichtigte Probleme schützen kann, läßt er die Tür offen zu bösem Code.

Beantwortet am 11/02/2010 um 14:22
quelle vom benutzer

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