DivinusVox
DivinusVox

Reputation: 1191

Binary Search Tree Destructor

Working on implementing my own BST in C++ for the experience of dealing with such structures.

I've had trouble implementing a destructor. I found in my studies, that one can't really have a recursive destructor (due to a flag that doesn't allow the destructor to be called on the same object after having been called), but I'm not really sure of any other way to successfully clean up all the nodes in the tree.

To compensate, I've created a helper function - however this throws an unresolved external error on the 'delete n' line. Any tips?

Code:

void BinSearchTree::Clear(tNode* n)
{
    if (n->left != NULL)
        Clear(n->left);
    if (n->right != NULL)
        Clear(n->right);
    delete n;
    n = NULL;
    size--;
}

Upvotes: 9

Views: 33843

Answers (6)

You can also use recursion, you just need to change the function header to:

void remove(node*& root) 

and it will work.

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264381

How about automating it:

class BinSearchTree
{
    std::auto_ptr<tNode>   left;
    std::auto_ptr<tNode>   right;

    BinSearchTree(BinSearchTree const&);
    BinSearchTree& operator=(BinSearchTree const&); // private
};

Now destruction is automatic. :-)

Upvotes: 1

01d55
01d55

Reputation: 1912

Previous answers have pointed out that the unresolved external error is likely caused by a tNode destructor that is declared but not defined in a translation unit that the linker can see.

However, you have a second error: You appear to believe that setting n to null does something it doesn't do. The pointer value n is passed by value, not by reference, such that changing its value (e.g. by assigning NULL) has no effect after the function returns.

This will probably give you errors when you clear the tree and expect the root node pointer to have been set to NULL, when it remains a dangling pointer to freed memory. The result will be runtime error, not your linker error.

void BinSearchTree::Clear(tNode **N)
{
    tNode * n = *N;
    if (n->left != NULL)
        Clear(n->left);
    if (n->right != NULL)
        Clear(n->right);
    delete n;
    *N = NULL;
    size--;
}

Will do what you expect.

Upvotes: 4

Jeremy Friesner
Jeremy Friesner

Reputation: 73051

You can have a recursive destructor; what you can't do is delete the same object twice.

A typical way to delete a tree in C++ might be something like this:

BinSearchTree::~BinSearchTree()
{
   delete _rootNode;  // will recursively delete all nodes below it as well
}

tNode::~tNode()
{
   delete left;
   delete right;
}

Regarding the unresolved external error -- is that error thrown when you try to compile/link the program? If so, it's probably because the code for the tNode class (and in particular the tNode destructor, if you declared one) doesn't exist or isn't getting compiled into your project.

Upvotes: 21

Brendan Long
Brendan Long

Reputation: 54242

Just use a destructors. It sounds like your problem is that you were trying to call the destructors directly, but the language handles this for you. They're called either when you leave a stack allocated object's scope, or when you delete an object.

All you should need is this:

~BinSearchTree() {
    delete left;
    delete right;
}

delete will call their destructors.

Note: It's perfectly safe to delete NULL, it has no effect.

Upvotes: 2

6502
6502

Reputation: 114461

The problem is that in you class you probably declared that the node structure has a custom destructor, but you don't provide it so at link time the compiler is complaining a piece is missing.

If you don't need any more custom code in the destructor then you can just remove the destructor from the struct declaration and your program will compile fine.

Note however that there is no problem at all to have a destructor of to destory children nodes (see Brendan Long answer). If you ran into problems while attempting that the issue you faced must me something else.

Upvotes: 3

Related Questions