I am having a weird issue. I ran the following program without the function call prePostInOrder(); and put it back into main and it works just fine but the moment I put the function call into use the program crashes. I ran a debugger and found that there was an issue in my freeTree when this function call was made so I commented out the delete r in freeTree() function that is located in my BST.h and it worked. Anyone know why its crashing?
I am using Microsoft Visual Studio 10
Here is my .cpp file, below that are my two .h files. Any help is very Appreciated!
#include <iostream>
#include "BST.h"
#include "BSTNode.h"
using namespace std;
void prePostInOrder(BST<int> tree);
int main()
{
int treeArray2[7] = {1, 2, 3, 4, 5, 6, 7};
BST<int> tree2;
for(int i = 0; i < 7; i++)
{
tree2.insert(treeArray2[i]);
}
T data;
BSTNode<T> *left;
BSTNode<T> *right;
BSTNode<T> *parent;
};
#endif /* BSTNODE_H_ */
Here is my BST.h file, The issue starts down at freeTree() at the bottom. If I comment out delete r in freeTree I do not have an issue? Does anyone know why?
#ifndef BST_H_
#define BST_H_
#include "BSTNode.h"
#include <list>
using namespace std;
// -----------------------------------
// code for the public methods
//------------------------------------
template<class T>
BST<T>::~BST()
{
freeTree(root); // free all the nodes in the tree
size = 0;
};
template<class T>
int BST<T>::maxDepth()
{
list<int> L;
findAllDepth(L, root, 0);
int max = 0;
list<int>::iterator i;
for (i = L.begin(); i != L.end(); ++i) {
if (max < *i) {
max = *i;
}
}
return max;
};
template<class T>
double BST<T>::averageProbeCount()
{
if (root == NULL) {
return 0;
} else {
list<int> L;
findAllDepth(L, root, 0);
int sum = 0;
list<int>::iterator i;
for (i = L.begin(); i != L.end(); ++i) {
sum += (*i + 1); // Note: # of probes is always 1+depth
}
return (double) (sum) / size; // note that it is an integer division
}
};
template<class T>
BSTNode<T>* BST<T>::findNewParent(T x, BSTNode<T> *r)
{
if (r == NULL) // empty tree
return NULL;
else if (x < r->data) { // go down left subtree
if (r->left == NULL)
return r;
else
return findNewParent(x, r->left);
} else { // x >= r->data
if (r->right == NULL)
return r;
else
return findNewParent(x, r->right);
}
}; // findNewParent
if (isLeaf(delNode)) { // case 1
if (delNode == root)
root = NULL;
else {
p = delNode->parent;
if (delNode == p->left)
p->left = NULL;
else
p->right = NULL;
}
delete delNode;
} else if (hasSingleChild(delNode)) { // case 2
BSTNode<T> *child =
(delNode->left == NULL) ? delNode->right : delNode->left;
if (delNode == root) {
root = child;
child->parent = NULL;
} else {
p = delNode->parent;
child->parent = p;
if (delNode == p->left)
p->left = child;
else
p->right = child;
}
delete delNode;
} else { // case 3
BSTNode<T> *pred = findMax(delNode->left);
if (pred == delNode->left) { // case 3b
delNode->data = pred->data;
delNode->left = pred->left;
if (delNode->left != NULL)
delNode->left->parent = delNode;
delete pred;
} else { // case 3a
delNode->data = pred->data;
remove(pred);
}
}
}; // end remove
// returns true if r is a leaf node
template<class T>
bool BST<T>::isLeaf(BSTNode<T> *r)
{
return r->left == NULL && r->right == NULL;
};
// returns true if r has only one child
template<class T>
bool BST<T>::hasSingleChild(BSTNode<T> *r)
{
return (r->left == NULL && r->right != NULL)
|| (r->left != NULL && r->right == NULL);
};
template<class T>
BSTNode<T>* BST<T>::findMax(BSTNode<T> *r)
{
if (r == NULL) // empty tree
return NULL;
else if (isLeaf(r)) // singleton tree
return r;
else if (r->right == NULL) // r is the largest node
return r;
else
// largest node is in r’s right subtree
return findMax(r->right);
};
The declaration of your function is like this: void prePostInOrder(BST<int> tree)
Notice that you're passing your tree object by value, so the compiler is going to call a copy constructor to create a copy of the tree object. Since you did not define a copy constructor/assignment operator for your tree object, the compiler will go ahead and define one for you. When the compiler defines a copy-constructor, it only performs a shallow copy of your object, meaning that it will copy all of your variables, but it will not create a copy of your dynamically allocated memory. Now you have a copy of your tree, but all the pointers are still referring to the originals.
The problem with that is once execution reaches the end of prePostInOrder, the compiler destroys the local copy of the tree object by calling the destructor... which happily destroys the allocated memory of your original tree object. Therefore, when you finish your main and try to clean up your original tree, you end up trying to free already deallocated memory.
You probably want to pass the tree to prePostInOrder by reference, like: void prePostInOrder(BST<int> &tree).