Waarom wordt mijn C ++ code niet aan alle knooppunten in mijn BST te schrappen?

stemmen
1

Dit wordt verondersteld een BST doorkruisen en elk knooppunt te verwijderen, met inbegrip van de root node. Echter, aan het eind, krijg ik het bericht root heeft nog steeds een links node. Waarom worden niet alle knooppunten verwijderd?

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;
}   
De vraag is gesteld op 11/02/2010 om 03:57
bron van user
In andere talen...                            


5 antwoorden

stemmen
6

Uw verwijdert paan het einde ( root) en dan proberen om de inhoud ervan in deleteTree(), waarbij rootniet langer punten toegewezen geheugen. Het resultaat zal worden undefined.

antwoordde op 11/02/2010 om 04:00
bron van user

stemmen
2

Je bent te verwijderen root. En dan is uw code probeert om toegang tot het geheugen waar het was.

Je bent goed in undefined-gedrag land daar.

antwoordde op 11/02/2010 om 04:01
bron van user

stemmen
2

Je moet niet dereference rootnadat u het verwijderen in deleteNode. Gebruik een debugger te inspecteren waarom root->leftis niet nul.

antwoordde op 11/02/2010 om 04:01
bron van user

stemmen
2

U bent op zoek naar root->leftnadat u al hebt verwijderd wortel, waardoor het voorraad voor gebruik in een nieuw toegewezen blok.

antwoordde op 11/02/2010 om 04:02
bron van user

stemmen
-1

Ik zou gewoon de boom zelf te veranderen, zou het gemakkelijker zijn om te gaan dan:

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

Door Object-Oriented, elk knooppunt is nu verantwoordelijk voor het geheugen wordt omgegaan. Ook het gebruik van std::auto_ptrin de interface maakt duidelijk dat het duurt ownership.

Merk op dat het is op maat gemaakt voor deep-kopiëren, een andere aanpak vereisen boost::shared_ptrof gelijkwaardig. En ja std::auto_ptrlaat je omgaan met het kopiëren door jezelf, geen magische daar.

Dit ontwerp is veel schoner dan het gebruik van een vlakte C-structmet iedereen de mogelijkheid om de middelen te manipuleren. Je hebt nog steeds volledige toegang tot de onderliggende gegevens via de accessor ... maar ze zorgen voor onbepaald gedrag geen beroep te doen ...

Natuurlijk kunt u nog steeds crashen naar beneden:

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

Maar als C ++ kan beschermen tegen onbedoelde kwesties, laat de deur open voor het kwade code.

antwoordde op 11/02/2010 om 14:22
bron van user

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