Destroy entire AVL tree - c++

I'm having a problem entirely deleting my AVL tree. I've figured out how to delete just a single node, but my destroyTree function doesn't seem to actually destroy every node recursively. What could I be doing wrong?
I have a struct nodeType<myType>
template <class myType>
struct nodeType {
myType keyValue;
int nodeHeight;
nodeType<myType> *left;
nodeType<myType> *right;
};
and I am attempted to delete all existing nodes with:
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
but this does not seem to properly delete the nodes, when checking for the height it still gives me the height before the destroy was called although crashes when attempting to print. In the main function calling destroy tree I used a simple if statement
template <class myType>
void avlTree<myType>::destroyTree()
{
destroyTree(root);
if(root == NULL)
std::cout << "destroyed" << std::endl;
}
shows that root is NOT null (yes is not printed)

Look at this piece of code:
destroyTree(root);
if(root == NULL)
std::cout << "destroyed" << std::endl;
Probably your destroyTree function has this prototype:
void destroyTree(nodeType<myType> *node);
The problem is that node cant update the caller memory address, but only the contents that caller is pointing. This means that root will never be update, i.e., its contents cant be updated to NULL.
To do that, you need a prototype that is something like that:
void destroyTree(nodeType<myType> **node);

I'm guessing you're not taking node by reference, and therefore when you set the node to NULL you're actually setting a local copy of the node to null.
Won't work because root is taken by value - will have prior value after function call:
template <class myType>
void avlTree<myType>::destroyTree(nodeType<myType>* node) // note node taken by value here
{
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
}
Will work because root is taken by reference - will be null after the function call:
template <class myType>
void avlTree<myType>::destroyTree(nodeType<myType>* &node) // note node taken by reference here
{
if(node != NULL) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
node = NULL;
}

Related

How do I write this node counter?

Hi I am trying to create a function that counts the number of nodes in the binary tree. I am getting an error that says mismatch of functions. I have gotten other errors and can't seem to get it to work. I know the idea just am having a hard time figuring this one out. Thank You! Edit - My error is mismatch of parameter list.
template<class T>
class BinaryTree
{
private:
struct TreeNode
{
T value;
TreeNode *left;
TreeNode *right;
};
TreeNode *root;
void insert(TreeNode *&, TreeNode *&);
void NodeNumber(TreeNode *&, int&); //My NodeNumber declaration
public:
BinaryTree()
{
root = nullptr;
}
void insertNode(T);
int NodeNum();
};
template <class T>
void BinaryTree<T>::insertNode(T item)
{
TreeNode *newNode = nullptr;
newNode = new TreeNode;
newNode->value = item;
newNode->left = newNode->right = nullptr;
insert(root, newNode);
}
template <class T>
void BinaryTree<T>::NodeNumber(TreeNode *&root, int&)
{
if (root = nullptr)
return;
else
root->right;
root->left;
count = count + 2;
}
template <class T>
int BinaryTree<T>::NodeNum()
{
int count = 0;
NodeNumber(root,count);
return count;
}
You have numerous mis-designs and errors in this class. I will focus on the outright errors. I don't know which of those mis-designs has been mandated by your professor and which are yours.
BinaryTree<T>::NodeNumber, as it is currently written, will crash every time. To figure out why, think carefully about exactly what this line does:
if (root = nullptr)
How does that line differ from these two?
root = nullptr;
if (root)
Secondly, what do the lines:
root->left;
and:
root->right;
do exactly? Why do you think they do that?
Lastly, when exactly should you be adding to count and why? Where is that true?
You didn't give a name to the 2nd parameter in this function, which I assume should be count.
// original
template <class T>
void BinaryTree<T>::NodeNumber(TreeNode *&root, int&)
{
if (root = nullptr)
return;
else
root->right;
root->left;
count = count + 2;
}
A few comments:
If you have a non-null root pointer, you want to visit both left and right child trees. It looks weird that right is in the "else" case, while left is not. I suggest getting rid of the "else" and just return if root is null, and otherwise process both left and right after the if.
You are not testing if the root pointer is null; you are setting it to null.
There is no reason to pass a reference to the root pointer
Your statements like "root->right" do not do anything. You want to recurse down the left child and recurse down the right child, so need to call NodeNumber again and pass your children as the root of these recursive calls, and also pass "count" down too.
Why do you increment by 2? Each node should only count as 1. (Its children will account for themselves as you recurse down them, so only add one for the node itself.)
I prefer to return the count rather than use an "out" parameter
Therefore, consider something like this:
template <class T>
int BinaryTree<T>::NodeNumber(TreeNode *root)
{
if (root == nullptr)
return 0;
int count = 1;
count += NodeNumber(root->right);
count += NodeNumber(root->left);
return count;
}
And of course, adjust the declaration and calls accordingly.

C++ Binary Search Tree Insert Implementation

I'm trying to build a function to insert into a binary search tree, but I'm having a hard time figuring out why it won't work. I understand fundamentally how the function is supposed to work, but based on the template I was given it seems as though I am to avoid creating a BST class but instead rely on the Node class and build the desired functions to work on that. Here's the given template:
#include <iostream>
#include <cstddef>
using std::cout;
using std::endl;
class Node {
int value;
public:
Node* left; // left child
Node* right; // right child
Node* p; // parent
Node(int data) {
value = data;
left = NULL;
right = NULL;
p = NULL;
}
~Node() {
}
int d() {
return value;
}
void print() {
std::cout << value << std::endl;
}
};
function insert(Node *insert_node, Node *tree_root){
//Your code here
}
The issue I'm having is when I implement the following code, where getValue is a simple getter method for Node:
int main(int argc, const char * argv[]) {
Node* root = NULL;
Node* a = new Node(2);
insert(a, root);
}
void insert(Node *insert_node, Node *tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());
The code appears to compile and run without error, but if I run another check on root after this, it returns NULL. Any idea what I'm missing here? Why is it not replacing root with a new node equal to that of insert_node?
I also realize this doesn't appear to be the optimal way to implement a BST, but I am trying to work with the template given to me. Any advice would be appreciated.
As Joachim said your issue relates to difference between passing parameter by reference and by value.
In your code void insert(Node *insert_node, Node *tree_root) you pass Node* tree_root by value. Inside the function you change local copy of this pointer, so outer value is not changed.
To fix it you should pass Node* tree_root by reference. Parameter declaration can be Node*& tree_root (or Node** tree_root). E.g:
void insert(Node* insert_node, Node*& tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());

Nodes of a list being freed before usage

I have a one-dimensional template list that contains nodes, each node has a link to next node.
It works rather well on it's own, but not when it contains another linked list.
LinkedList and Node looks something like that:
template <class T>
class LinkedList
{
private:
Node<T>* pPreHead;
public:
LinkedList(void);
~LinkedList(void);
Node<T>* getHead(void);
int size();
void addElementToEnd(T& value);
void deleteNextNode(Node<T>* pNodeBefore);
}
template <class T>
class Node
{
private:
T value;
Node* next;
public:
Node();
Node* getNext();
Node* getValue();
void setNext(Node* nextElem);
void setValue(T elem);
};
Now for the task I need to use LinkedList>, which is filled via a loop.
It looks something like this:
ifstream fl;
fl.open("test1.in", std::ifstream::in);
while (fl.good())
{
string currentLine;
getline(fl, currentLine);
LinkedList<string> newDNA;
//newDNA being filled here so I skipped code
DNAStorage.addElementToEnd(newDNA);
//Place 1
}
//Place 2
Now if I insert some test output code in "Place 1" everything is fine, but when the loop enters new iteration newDNA variable gets freed and so is the pointer inside DNAStorage (which is LinkedList<LinkedList<string>> in question), and when I try to print anything in "Place 2" I get segmentation fault.
Unfortunately I can't use any other data structures since this is the kind of task I need to do.
My question is - how can this be fixed, so that it actually is not freed prematurely?
Edit:
Here's my code for AddElementToEnd(T& value):
template <class T>
void LinkedList<T>::addElementToEnd(T &value)
{
Node<T> *newtail = new Node<T>;
newtail.setNext(NULL);
newtail.setValue(value);
if(pPreHead == NULL)
{
pPreHead = newtail;
return;
}
Node<T> *tail = pPreHead;
while(tail.getNext() != NULL)
{
tail = tail.getNext();
}
tail.setNext(newtail);
}
The problem is that you are storing references to objects that are going out of scope, causing undefined behavior when you try and access them. Your LinkedList<string> newDNA gets created and destroyed with each iteration of the while loop, yet you pass a reference to be stored in DNAStorage list.
One solution would be to store a copy of each object (not reference) in the list when addElementToEnd() gets called.

Unexpected Pointer behavior

I am confused with what exactly goes wrong in the following demo code. I expected that the next would keep pointing to the next element in the chain until reached end. However, I get EXE_BAD_ADDESS error. I guess I am missing something in the recursive pointer assignment.
template <class T>
struct Node {
Node *left, *right, *parent;
int height;
T value;
// constructor
Node(T val)
: value(val){
height = 0;
left = right = NULL;
}
};
template <class T>
void assignToNext(Node<T> *n, Node<T> *next){
// base case
if (n == NULL)
return;
// else assign to this node and check for next
next = n;
assignToNext(n->left, next);
}
And then in the main:
Node<int> a(1);
a.left = new Node<int>(2);
a.left->left = new Node<int>(3);
a.left->left->left = new Node<int>(4);
a.left->left->left->left = new Node<int>(5);
Node<int> *last = NULL;
assignToNext(&a, last);
std::cout << last->value << std::endl; // I get EXE_BAD_ADDRESS error
Thanks in advance,
Nikhil
void assignToNext(Node<T> *n, Node<T> *next){
-->
void assignToNext(Node<T> *n, Node<T> *&next){ // note the &
Otherwise the original pointer isn't updated and stays NULL.
assignToNext(&a, last);
This code can't modify local variable Node<int> *last's value. You just passed NULL to parameter Node<T> *next. So last's value is still NULL and you got error. If you want modify pointer's value, use double pointer.
Like,
void assignToNext(Node<T> *n, Node<T> **next);
assignToNext(&a, &last);

C++ linked binary search tree (DeleteTree)

I have to implement a binary search tree using C++ for one of assignments. I've created the class, and attempted to implement the InsertItem, PrintTree, DeleteTree methods for the class, I think I did everything right but for some reason my program keeps crashing :(
Here's my code:
PrintTree Method
template <class TItem>
void BinarySearchTree<TItem>::PrintTree()
{
PrintTree(RootNode);
}
template <class TItem>
void BinarySearchTree<TItem>::PrintTree(BinarySearchTreeNode* Node)
{
if(Node == NULL)
return;
cout << Node->Data << endl;
PrintTree(Node->LeftChild);
PrintTree(Node->RightChild);
}
DeleteTree Method
template <class TItem>
void BinarySearchTree<TItem>::DeleteTree()
{
DeleteTree(RootNode);
}
template <class TItem>
void BinarySearchTree<TItem>::DeleteTree(BinarySearchTreeNode* Node)
{
if(Node == NULL)
return;
DeleteTree(Node->LeftChild);
DeleteTree(Node->RightChild);
delete Node;
}
My sequence of method calls up until the program crashes:
I insert items F,B,G,A,D,I,C,E,H: works fine
I call PrintTree(): works fine
I call DeleteTree(): works fine
I call PrintTree() again: program crashes
For some reason the expression if(RootNode == NULL) is not returning true after the DeleteTree() method is called, so the program tries to print something that doesn't exist and crashes. I'm not sure why this is happening, what am I doing wrong here?
Any and all help is appreciated.
Calling "delete" does not null out the pointer.
You will want to do:
delete Node;
Node = nullptr;
EDIT:
Pass the pointer by address so that you can clean up dangling pointers as you go:
void BinarySearchTree<TItem>::DeleteTree(BinarySearchTreeNode *&node);
I think the delete function should be changed to the following,
template <class TItem>
void BinarySearchTree<TItem>::DeleteTree(BinarySearchTreeNode** Node)
{
if((*Node) == NULL)
return;
DeleteTree(&(*Node)->LeftChild);
DeleteTree(&(*Node)->RightChild);
delete (*Node);
(*Node) = NULL;
}
Please correct me if I am wrong.