Templated binary search tree c++, unresolved external error - c++

I am working on a template for a binary search tree and I am getting the error below. I know there are similar post but I can't figure this thing out. Templates are definitely a weak subject for me so I think I am missing some fundamental semantic thing but I can put my finger on it. Below is the error than after that are the files of the program. If anyone could point me in the right direction I would really appreciate it.
Error 1 error LNK2019: unresolved external symbol "private: bool __thiscall Tree::insertHelper(class TreeNode * &,int)" (?insertHelper#?$Tree#H##AAE_NAAPAV?$TreeNode#H##H#Z) referenced in function "public: bool __thiscall Tree::insert(int)" (?insert#?$Tree#H##QAE_NH#Z) C:\Users\wm\documents\visual studio 2012\Projects\binaryTree\binaryTree\main.obj
-basic main for testing
#include "BinarySearchTree.h"
#include "TreeNode.h"
#include <iostream>
using namespace std;
int main()
{
Tree<int> test;
test.insert(55);
return 0;
}
-tree template
#include <iostream>
#include "TreeNode.h"
using namespace std;
template< class ItemType >
class Tree {
public:
Tree();
~Tree();
bool isEmpty() const;
void makeEmpty();
bool insert( ItemType newItem);
bool retrieve( ItemType searchItem, ItemType & foundItem );
bool deleteItem (ItemType deleteItem);
void print();
private:
TreeNode< ItemType > * rootPtr; // pointer to the root
//utility functions
void printHelper( TreeNode< ItemType > * );
bool insertHelper(TreeNode< ItemType > * & node, ItemType item);
bool deleteHelper( TreeNode< ItemType > * & , ItemType );
void deleteNode( TreeNode<ItemType > * & );
bool retrieveHelper( ItemType, TreeNode< ItemType > * & , ItemType & );
};
template<class ItemType>
Tree<ItemType>::Tree()
{
rootPtr = NULL;
}
template<class ItemType>
Tree<ItemType>::~Tree()
{
makeEmpty();
}
template<class ItemType>
bool Tree<ItemType>::isEmpty() const
//Returns True if the tree is empty, otherwise returns false
//Postcondition: Tree is unchanged.
{
if(rootPtr == NULL)
{
return true;
}
else
{
return false;
}
}
template<class ItemType>
void Tree<ItemType>::makeEmpty()
//Makes the tree empty if it is not empty already.
//Preconditions: The tree exists.
//Postconditions: Tree is now empty. Any dynamically allocated memory which is no longer used is returned to the system.
{
return;
}
template<class ItemType>
bool Tree<ItemType>::insert( ItemType newItem)
// Inserts a copy of newItem in the tree.
//Precondition: The tree exists and has binary search property.
//Postcondition: if the tree already has an item where item == newItem, the function returns false and the trre is unchanged.
//Otherwise, the newItem is inserted in the tree preserving and the binary search property is maintained.
{
if(rootPtr == NULL)
{
rootPtr->data = newItem;
return true;
}
else
{
return insertHelper(rootPtr, newItem);
}
}
template<class ItemType>
bool insertHelper( TreeNode< ItemType > * & node, ItemType item)
{
if( item < node->data)//left
{
if(node->leftPtr == NULL)
{
node->leftPtr = new TreeNode<ItemType>(item);
return true;
}
else
{
return insertHelper(node->leftPtr,item);
}
}
else if(node->data < item)//right
{
if(node->righChild == NULL)
{
node->rightPtr = new TreeNode<ItemType>(item);
return true;
}
else
{
return insertHelper(node->rightPtr,item);
}
}
else// same value
{
return false;
}
}
template<class ItemType>
bool Tree<ItemType>::retrieve( ItemType searchItem, ItemType & foundItem )
// Given a searchItem, it tries to retrieve as foundItem, an item in the tree where the item == searchItem.
// Precondition:The tree exists and has the binary search property.
// Postcondition: If the tree already has an item where item == searchItem, foundItem is set to that item, and the function returns true.
// If the tree has no such item, the function returns false and foundItem remains unchanged. The tree is unchanged.
{
}
template<class ItemType>
bool Tree<ItemType>::deleteItem (ItemType deleteItem)
// Given a deleteItem, it deltes from the tree any item where item == deleteItem.
// Precondition: Tree exists and has binary search property.
// Postcondition: If the tree has an item where item == deleteItem, that item is removed from the tree, and the function returns true, and
// the binary search property is maintained. If the tree has no such item, the function returns false and the tree remains unchanged.
{
}
template<class ItemType>
void Tree<ItemType>::print()
// Prints the items in the tree in ascending order to the screen
// Precondition: The tree exists and has binary search property.
// Postcondition: The items have been printed in ascending order and the tree is unchanged
{
}
template<class ItemType>
void printHelper( TreeNode< ItemType > * )
{
}
template<class ItemType>
bool deleteHelper( TreeNode< ItemType > * & , ItemType )
{
}
template<class ItemType>
void deleteNode( TreeNode<ItemType > * & )
{
}
template<class ItemType>
bool retrieveHelper( ItemType, TreeNode< ItemType > * & , ItemType & )
{
}
-treenode
#ifndef TREENODE_H
#define TREENODE_H
template< class ItemType > class Tree; // forward declarations
template<class ItemType>
class TreeNode {
friend class Tree< ItemType >; // make Tree a friend
public:
TreeNode( ItemType ); // constructor
TreeNode(); // constructor with data uninitialized
ItemType getData() const; // return data in the node
private:
ItemType data;
TreeNode< ItemType > *leftPtr;
TreeNode< ItemType > *rightPtr;
};
// Constructor
template<class ItemType>
TreeNode< ItemType >::TreeNode( ItemType newItem )
{
data = newItem;
leftPtr = NULL;
rightPtr = NULL;
}
template<class ItemType>
TreeNode< ItemType >::TreeNode( )
{
leftPtr = NULL;
rightPtr = NULL;
}
// Return a copy of the data in the node
template< class ItemType >
ItemType TreeNode< ItemType >::getData() const
{
return data;
}
#endif

Heh. The problem is that you forgot the scoping qualifier Tree<ItemType>:: in front of the function name for insertHelper.
Just do this:
template<class ItemType>
bool Tree<ItemType>::insertHelper( TreeNode< ItemType > * & node, ItemType item)
By the way, the linker error should suggest to you that this is the problem. First of all, you know that you have a link problem, not a compile problem. Second, you know the symbol that can't be found is *Tree<ItemType>::*insertHelper(...). Third, you know that a call to that function was successfully compiled in Tree<ItemType>::insert, which means the compiler found and parsed the declaration for the insertHelper method without problem. The only possible explanation for the linker not being able to find the actual object code for the method is that the definition of the function either doesn't exist or doesn't have the same name that you declared it as!

Here:
if(rootPtr == NULL)
{
rootPtr->data = newItem;
return true;
}
If rootPtr is NULL then rootPtr->data is not valid.
Maybe you meant:
if(rootPtr == NULL)
{
rootPtr = new TreeNode<ItemType>(newItem);
}

Related

Recursive remove in linked list

I am trying to remove the element from linked list recursively, but the remove function is not working. I need some help in solving this.
My node.h function
#ifndef NODE_
#define NODE_
template<class ItemType>
class Node {
private:
ItemType item; // A data item
Node<ItemType>* next; // Pointer to next node
public:
Node();
Node(const ItemType& anItem);
Node(const ItemType& anItem, Node<ItemType>* nextNodePtr);
void setItem(const ItemType& anItem);
void setNext(Node<ItemType>* nextNodePtr);
ItemType getItem() const;
Node<ItemType>* getNext() const;
}; // end Node
#include "Node.cpp"
#endif
My node.cpp file:
#include "Node.h"
template<class ItemType>
Node<ItemType>::Node() : next(nullptr)
{
} // end default constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem) : item(anItem), next(nullptr)
{
} // end constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem, Node<ItemType>* nextNodePtr) :
item(anItem), next(nextNodePtr)
{
} // end constructor
template<class ItemType>
void Node<ItemType>::setItem(const ItemType& anItem)
{
item = anItem;
} // end setItem
template<class ItemType>
void Node<ItemType>::setNext(Node<ItemType>* nextNodePtr)
{
next = nextNodePtr;
} // end setNext
template<class ItemType>
ItemType Node<ItemType>::getItem() const
{
return item;
} // end getItem
template<class ItemType>
Node<ItemType>* Node<ItemType>::getNext() const
{
return next;
} // end getNext
My main function:
#include <iostream>
#include "Node.h"
using namespace std;
// Function to insert an item into the front of a linked list
template<class T>
void insert(Node<T>* &headPtr, const T& entry)
{
// Create a new node and have the next pointer point to current front
Node<T> *newNodePtr = new Node<T>( entry , headPtr );
// Current front now becomes this new node
headPtr = newNodePtr;
}
// Recursive function to remove an item from a linked list
// Returns true if the operation was done; false, otherwise
template< typename T >
bool removes(Node<T>* &nodePtr, T target)
{
if(!nodePtr)
{
return false;
}
if(nodePtr->getNext() != NULL)
{
Node<T>*next = nodePtr->getNext();
removes(next,target);
if(nodePtr->getNext()->getItem()==target)
{
Node<T>*del = nodePtr;
nodePtr->setNext(nodePtr->getNext()->getNext());
delete del;
return true;
}
//nodePtr->setNext(nodePtr->getNext());
}
}
// Recursive function to display the contents of a linked list
// in the reverse order.
template<class T>
void display(Node<T> *currNodePtr)
{
// YOUR CODE GOES HERE - CHECK YOUR NOTES!
Node<T> *curr=currNodePtr;
if(curr!=NULL)
{
cout<<curr->getItem();
display(curr->getNext());
}
cout<<endl;
}
int main()
{
// (1) Declare an empty linked list of unsigned values
// based on the Node class and call it myList
Node<unsigned>*myList;
// (2) Read in values from standard input. Non-negative
// values are inserted into myList and a negative
// value terminates input.
int data=0;
unsigned k;
while(cin>>data)
{
if (data>=0)
{
k=data;
insert(myList,k);
}
else
{
break;
}
}
cout<<"out of loop";
// (3) Display the contents of the linked list myList
// in the order they were entered (hence, the display()
// function displays myList in reverse order!
display(myList);
// (4) Read in values from standard input. Non-negative
// values are removed from myList and a negative
// value terminates input.
int data1=0;
unsigned m;
while(cin>>data1)
{
if (data1>=0)
{
m=data1;
removes(myList,m);
}
else
{
break;
}
}
// (5) Display the contents of the linked list myList
// in the order they were entered (hence, the display()
// function displays myList in reverse order!
cout<<endl;
display(myList);
}
The remove function is in main. It is not removing the correct element. For example, in the list of 1 2 3 4 5, if I try to remove 3 it is removing 2.

How to insert a new node into a binary tree c++ while using a template class for ItemType. (I am new to c++)

So I am not really sure how the Template Class and the ItemType are interacting here. Should I just be changing root->data to the value? I keep getting a seg fault when doing that. So I figured I would have to create a new node and then assign that to the new root node?
Here's what I have so far. Thank for any help :)
The part I am having trouble with is adding a new Node. Specifically I have trouble with the line in the first if statement. I am not sure how to do it.
I thought it would be as simple as
root->data = value;
.....but its not
Main.cpp is below...
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <climits>
using namespace std;
#include "tree.h"
int main (void)
{
TreeType <int> tree;
srand(100);
cout<<"\nINSERTING\n";
for (int i=0;i<15;i++)
{
int number=rand()%100;
cout<<"Atttempting to insert "<<number<<endl;
tree.Insert(number);
}
cout<<"\nPRINT ALL\n";
tree.Print();
cout<<endl;
int array[16]={40,23,1,5,28,84,81,80,97,90,47,56,70,71,79,90};
for(int i=0;i<16;i++)
{
if (tree.DeleteItem(array[i]))
cout<<"Attempting to delete "<<array[i]<<endl;
}
cout<<"\nPRINT ALL\n";
tree.Print();
return 0;
}
Treend.h is below...
#ifndef TREEND_H
#define TREEND_H
template <class NODETYPE>
class TreeNode{
public:
TreeNode(const NODETYPE &value);
TreeNode(){right=0;left=0;}
TreeNode<NODETYPE> *left, *right;
NODETYPE data;
};
template<class NODETYPE>
TreeNode<NODETYPE>::TreeNode(const NODETYPE &value)
{
left = 0;
right = 0;
data = value;
}
#endif
tree.h is below...
#ifndef TREE
#define TREE
#include <fstream>
#include <iostream>
using namespace std;
#include "Treend.h"
template<class ItemType>
class TreeType
{
public:
TreeType();
TreeType (const TreeType &original){CopyTree(root, original.root);}
void operator=(TreeType &orginalTree);
bool Search(ItemType &value);
void Insert(ItemType value);
void Print();
~TreeType();
bool isEmpty() {return root==0;}
bool DeleteItem(ItemType value);
bool PrintOne(ItemType value);
void Update(ItemType value, ItemType &newvalue);
private:
TreeNode<ItemType>* root;
void CopyTree(TreeNode<ItemType>*& copy, const TreeNode<ItemType>* original);
bool BinarySearch(TreeNode<ItemType>* root, ItemType &value);
void InsertItem(TreeNode<ItemType>*& root, ItemType value);
void PrintTree(TreeNode<ItemType>* root);
void Destroy(TreeNode<ItemType>*& root);
bool PrintOneNode(TreeNode<ItemType>* root, ItemType value);
bool UpdateTree(TreeNode<ItemType>*& root, ItemType value, ItemType newvalue);
bool Delete(TreeNode<ItemType>*& root, ItemType);
void FindMin(TreeNode<ItemType>* root, ItemType &data);
};
#include "tree.cpp"
#endif
Unfinished tree.cpp below... (working on insert now)
#include "tree.h"
#ifndef TREE_CPP
#define TREE_CPP
template<class ItemType>
void TreeType<ItemType>::operator=(TreeType<ItemType> &original)
{
if(original == this)
return; //ignore assigning self to self
Destroy(root);
CopyTree(root, original.root);
cout<<"";
}
template<class ItemType>
void TreeType<ItemType>::CopyTree(TreeNode<ItemType>*& copy, const TreeNode<ItemType>* original)
{
if (original == NULL)
copy = NULL;
else
{
copy = new TreeNode<ItemType>;
copy-> data = original->data;
CopyTree(copy->left, original->left);
CopyTree(copy->right, original->right);
}
}
template<class ItemType>
bool TreeType<ItemType>::DeleteItem(ItemType item)
{
return Delete(root, item);
}
template<class ItemType>
void TreeType <ItemType>::FindMin(TreeNode <ItemType>* root, ItemType &data)
{
while(root->left != 0)
{
root = root->left;
}
data = root->data;
}
template<class ItemType>
TreeType<ItemType>::~TreeType()
{
Destroy(root);
}
template <class ItemType>
void TreeType<ItemType>::Destroy(TreeNode<ItemType>*& root)
{
}
template <class ItemType>
bool TreeType<ItemType>::BinarySearch(TreeNode<ItemType>* root, ItemType &value)
{
if(root == 0)
{
cout<<value<<" not found\n";
return false;
}
else if(root->data == value)
{
value = root->data;
return true;
}
else if (root->data <= value)
return(BinarySearch(root->right, value));
else
return(BinarySearch(root->left, value));
}
template <class ItemType>
TreeType<ItemType>::TreeType()
{
root = 0;
}
template <class ItemType>
bool TreeType<ItemType>::Search(ItemType &value)
{
return(BinarySearch(root, value));
}
template<class ItemType>
void TreeType<ItemType>::Insert(ItemType item)
{
InsertItem(root, item);
}
//changed the ItemType from TreeNode
template<class ItemType>
void TreeType<ItemType>::InsertItem(TreeNode<ItemType>*& root, ItemType value)
{
// no nodes exist yet.
if (root->data == 0) {
root = new TreeNode<ItemType>(value);
} else if (root->data > value) {
InsertItem(root->left, value);
} else if (root->data < value) {
InsertItem(root->right, value);
}
}
template<class ItemType>
void TreeType<ItemType>::Print()
{
PrintTree(root);
}
template <class ItemType>
void TreeType<ItemType>::PrintTree(TreeNode<ItemType>* root)
{
}
template <class ItemType>
bool TreeType<ItemType>::PrintOne(ItemType value)
{
return (PrintOneNode(root, value));
}
template <class ItemType>
bool TreeType<ItemType>::PrintOneNode(TreeNode<ItemType>* root, ItemType value)
{
if(root == 0)
{cout<<"Not Found"<<endl;
return false;
}
else if (root-> data == value)
{
cout << root->data;
return false;
}
else if (root -> data >= value)
return PrintOneNode(root->left, value);
else
return PrintOneNode(root->right, value);
}
template <class ItemType>
void TreeType<ItemType>::Update(ItemType value, ItemType &newvalue)
{
UpdateTree(root, value, newvalue);
}
template <class ItemType>
bool TreeType<ItemType>::UpdateTree(TreeNode <ItemType>*& root, ItemType value, ItemType newvalue)
{
}
template<class ItemType>
bool TreeType<ItemType>::Delete(TreeNode<ItemType>*& root, ItemType item)
{
}
#endif
As this seems to be a problem for a class I will Refrain from blindly providing code. adding a node isn't simply adding the data to an empty node. Remember a node is made of data and pointers. You first need to find the location were the node needs to go. This is usually done recursively. Once the correct spot is found, then you add the node. Hope this helps.
if (!root) {
root = new TreeNode<ItemType>();
root->value = value;
} ect
Credit To:
https://chat.stackoverflow.com/users/7703024/super

functionname redefinition; different basic types

I'm getting the following error:
error C2371: 'BinarySearchTree::isComplete' : redefinition; different basic types
This is my header file:
#ifndef BinarySearchTree_H
#define BinarySearchTree_H
#include <iostream>
#include "Queue.h"
#include <cmath>
using namespace std;
template <class T>
struct TreeNode;
enum OrderType {PRE_ORDER, IN_ORDER, POST_ORDER};
template <class T>
class BinarySearchTree
{
public:
BinarySearchTree(); // Constructor.
~BinarySearchTree(); // Destructor.
BinarySearchTree(const BinarySearchTree& originalTree); // Copy constructor.
void operator=(const BinarySearchTree& originalTree);
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
int LengthIs() const;
void RetrieveItem(T& item, bool& found) const;
void InsertItem(T item);
void DeleteItem(T item);
void ResetTree(OrderType order);
void GetNextItem(T& item, OrderType order,bool& finished);
void Print(std::ostream& outFile, OrderType order) const;
int countMaxDepth();
void arrayBST(T * a);
bool isComplete();
bool isComplete(TreeNode* node);
private:
TreeNode<T>* root;
Queue<T> preQue;
Queue<T> inQue;
Queue<T> postQue;
};
template <class T>
int CountNodes(TreeNode<T>* tree);
template <class T>
void GetPredecessor(TreeNode<T>* tree, T& data);
template <class T>
void Destroy(TreeNode<T>*& tree);
template <class T>
void CopyTree(TreeNode<T>*& copy, const TreeNode<T>* originalTree);
template <class T>
void PreOrder(TreeNode<T>*, Queue<T>&);
template <class T>
void InOrder(TreeNode<T>*, Queue<T>&);
template <class T>
void PostOrder(TreeNode<T>*, Queue<T>&);
template <class T>
void PrintTree(TreeNode<T>* tree, std::ostream& outFile);
template <class T>
int maxDepth(TreeNode<T>* tree);
#endif
This is my implementation file:
#include "BinarySearchTree.h"
#include "Queue.h"
#include "Queue.cpp"
template <class T>
struct TreeNode
{
T info;
TreeNode<T>* left;
TreeNode<T>* right;
};
template <class T>
bool BinarySearchTree<T>::IsFull() const
// Returns true if the free store has no room for another node
// and false otherwise.
{
TreeNode<T>* location;
try
{
location = new TreeNode<T>;
delete location;
return false;
}
catch(std::bad_alloc exception)
{
return true;
}
}
template <class T>
bool BinarySearchTree<T>::IsEmpty() const
// Returns true if the tree is empty and false otherwise.
{
return root == NULL;
}
template <class T>
int BinarySearchTree<T>::LengthIs() const
// Calls the recursive function CountNodes to count the
// nodes in the tree.
{
return CountNodes(root);
}
template <class T>
int CountNodes(TreeNode<T>* tree)
// Post: Returns the number of nodes in the tree.
{
if (tree == NULL)
return 0;
else
return CountNodes(tree->left) + CountNodes(tree->right) + 1;
}
template <class T>
void BinarySearchTree<T>::RetrieveItem(T& item, bool& found) const
// Calls recursive function Retrieve to search the tree for item.
{
Retrieve(root, item, found);
}
template <class T>
void Retrieve(TreeNode<T>* tree,
T& item, bool& found)
// Recursively searches tree for item.
// Post: If there is an element someItem whose key matches item's,
// found is true and item is set to a copy of someItem;
// otherwise, found is false and item is unchanged.
{
if (tree == NULL)
found = false; // item is not found.
else if (item < tree->info)
Retrieve(tree->left, item, found); // Search left subtree.
else if (item > tree->info)
Retrieve(tree->right, item, found);// Search right subtree.
else
{
item = tree->info; // item is found.
found = true;
}
}
template <class T>
void BinarySearchTree<T>::InsertItem(T item)
// Calls the recursive function Insert to insert item into tree.
{
Insert(root, item);
}
template <class T>
void Insert(TreeNode<T>*& tree, T item)
// Inserts item into tree.
// Post: item is in tree; search property is maintained.
{
if (tree == NULL)
{// Insertion place found.
tree = new TreeNode<T>;
tree->right = NULL;
tree->left = NULL;
tree->info = item;
}
else if (item < tree->info)
Insert(tree->left, item); // Insert in left subtree.
else
Insert(tree->right, item); // Insert in right subtree.
}
template <class T>
void BinarySearchTree<T>::DeleteItem(T item)
// Calls the recursive function Delete to delete item from tree.
{
Delete(root, item);
}
template <class T>
void Delete(TreeNode<T>*& tree, T item)
// Deletes item from tree.
// Post: item is not in tree.
{
if (item < tree->info)
Delete(tree->left, item); // Look in left subtree.
else if (item > tree->info)
Delete(tree->right, item); // Look in right subtree.
else
DeleteNode(tree); // Node found; call DeleteNode.
}
template <class T>
void DeleteNode(TreeNode<T>*& tree)
// Deletes the node pointed to by tree.
// Post: The user's data in the node pointed to by tree is no
// longer in the tree. If tree is a leaf node or has only one
// non-NULL child pointer, the node pointed to by tree is
// deleted; otherwise, the user's data is replaced by its
// logical predecessor and the predecessor's node is deleted.
{
T data;
TreeNode<T>* tempPtr;
tempPtr = tree;
if (tree->left == NULL)
{
tree = tree->right;
delete tempPtr;
}
else if (tree->right == NULL)
{
tree = tree->left;
delete tempPtr;
}
else
{
GetPredecessor(tree->left, data);
tree->info = data;
Delete(tree->left, data); // Delete predecessor node.
}
}
template <class T>
void GetPredecessor(TreeNode<T>* tree, T& data)
// Sets data to the info member of the rightmost node in tree.
{
while (tree->right != NULL)
tree = tree->right;
data = tree->info;
}
template <class T>
BinarySearchTree<T>::BinarySearchTree()
{
root = NULL;
}
template <class T>
BinarySearchTree<T>::~BinarySearchTree()
// Calls recursive function Destroy to destroy the tree.
{
Destroy(root);
}
template <class T>
void Destroy(TreeNode<T>*& tree)
// Post: tree is empty; nodes have been deallocated.
{
if (tree != NULL)
{
Destroy(tree->left);
Destroy(tree->right);
delete tree;
}
}
template <class T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T>& originalTree)
// Calls the recursive function CopyTree to copy originalTree
// into root.
{
CopyTree(root, originalTree.root);
}
template <class T>
void BinarySearchTree<T>::operator=
(const BinarySearchTree<T>& originalTree)
// Calls the recursive function CopyTree to copy originalTree
// into root.
{
{
if (&originalTree == this)
return; // Ignore assigning self to self.
Destroy(root); // Deallocate existing tree nodes.
CopyTree(root, originalTree.root);
}
}
template <class T>
void CopyTree(TreeNode<T>*& copy,
const TreeNode<T>* originalTree)
// Post: copy is the root of a tree that is a duplicate
// of originalTree.
{
if (originalTree == NULL)
copy = NULL;
else
{
copy = new TreeNode<T>;
copy->info = originalTree->info;
CopyTree(copy->left, originalTree->left);
CopyTree(copy->right, originalTree->right);
}
}
template <class T>
void BinarySearchTree<T>::ResetTree(OrderType order)
// Calls a function to create a queue of the tree elements in
// the desired order.
{
switch (order)
{
case PRE_ORDER : PreOrder(root, preQue);
break;
case IN_ORDER : InOrder(root, inQue);
break;
case POST_ORDER: PostOrder(root, postQue);
break;
}
}
template <class T>
void PreOrder(TreeNode<T>* tree,
Queue<T>& preQue)
// Post: preQue contains the tree items in preorder.
{
if (tree != NULL)
{
preQue.Enqueue(tree->info);
PreOrder(tree->left, preQue);
PreOrder(tree->right, preQue);
}
}
template <class T>
void InOrder(TreeNode<T>* tree, Queue<T>& inQue)
// Post: inQue contains the tree items in inorder.
{
if (tree != NULL)
{
InOrder(tree->left, inQue);
inQue.Enqueue(tree->info);
InOrder(tree->right, inQue);
}
}
template <class T>
void PostOrder(TreeNode<T>* tree,
Queue<T>& postQue)
// Post: postQue contains the tree items in postorder.
{
if (tree != NULL)
{
PostOrder(tree->left, postQue);
PostOrder(tree->right, postQue);
postQue.Enqueue(tree->info);
}
}
template <class T>
void BinarySearchTree<T>::GetNextItem(T& item,
OrderType order, bool& finished)
// Returns the next item in the desired order.
// Post: For the desired order, item is the next item in the queue.
// If item is the last one in the queue, finished is true;
// otherwise, finished is false.
{
finished = false;
switch (order)
{
case PRE_ORDER : preQue.Dequeue(item);
if (preQue.IsEmpty())
finished = true;
break;
case IN_ORDER : inQue.Dequeue(item);
if (inQue.IsEmpty())
finished = true;
break;
case POST_ORDER: postQue.Dequeue(item);
if (postQue.IsEmpty())
finished = true;
break;
}
}
template <class T>
void PrintTree(TreeNode<T>* tree, std::ostream& outFile, OrderType order)
// Prints info member of items in tree in sorted order on outFile.
{
switch (order)
{
case PRE_ORDER :
if (tree != NULL)
{
outFile << tree->info;
PrintTree(tree->left, outFile ,order); // Print left subtree.
PrintTree(tree->right, outFile, order); // Print right subtree.
}
break;
case IN_ORDER :
if (tree != NULL)
{
PrintTree(tree->left, outFile, order); // Print left subtree.
outFile << tree->info;
PrintTree(tree->right, outFile, order); // Print right subtree.
}
break;
case POST_ORDER :
if (tree != NULL)
{
PrintTree(tree->left, outFile, order); // Print left subtree.
PrintTree(tree->right, outFile, order); // Print right subtree.
outFile << tree->info;
}
break;
default:;
}
}
template <class T>
void BinarySearchTree<T>::Print(std::ostream& outFile, OrderType order) const
// Calls recursive function Print to print items in the tree.
{
PrintTree(root, outFile, order);
outFile << endl;
}
template <class T>
int BinarySearchTree<T>::countMaxDepth()
{
return maxDepth(root)-1;
}
template <class T>
int maxDepth(TreeNode<T>* tree)
{
if(tree == NULL)
return 0;
else
{
int lDepth = maxDepth(tree->left);
int rDepth = maxDepth(tree->right);
if(lDepth > rDepth )
return lDepth+1;
else
return rDepth+1;
}
}
template <class T>
void BinarySearchTree<T>::arrayBST(T * a)
{
T temp;
bool f;
a = new T(CountNodes(root));
ResetTree(IN_ORDER);
for (int i = 0; i < LengthIs(); i++)
{
GetNextItem(temp, IN_ORDER, f);
a[i] = temp;
}
}
template <class T>
bool BinarySearchTree<T>::isComplete()
{
return isComplete(root);
}
template <class T>
bool BinarySearchTree<T>::isComplete(TreeNode<T>* node)
{
if (node == NULL)
return true;
if ((node->left == NULL && node->right != NULL) || (node->left != NULL && node->right == NULL))
return false;
return isComplete(node->left) && isComplete(node->right);
}
I've done some googling but it's been no use. Does anyone know what the problem is?
I think that the problem is that in the function declaration it should be:
template <class T>
class BinarySearchTree
{
public:
//...
bool isComplete(TreeNode<T>* node);
};
Or else the compiler will think it is a pointer to a non-template TreeNode type.
Maybe this non-template type does exist somewhere in your code. Or maybe you have more error messages that relate to that line. Or maybe your including of the .cpp file is messing with the linker, as the contents of that .cpp file may be compiled twice.
Do not #include one .cpp file into another.
You will have to move your class template's functions into the header from the .cpp file. See also http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html.
I see references to pointers (e.g., TreeNode<T>*&). That looks fishy.

linkedList remove_all function

I'm writing list and iterator classes function and I'm almost done, but I get some errors in the main file, that when I write the list remove_all function, but when I delete it there is no error anywhere, I don't know why!! Also, actually I'm not sure about my Iterator operators and the bool Iterator::is_item()
Any help is appreciated. Thanks
here is my codes:
Node.h
pragma once
namespace list_1
{
template <typename T>
struct Node
{
T data;
Node<T> *next;
// Constructor
// Postcondition:
Node<T> (T d);
};
template <typename T>
Node<T>::Node(T d)
{
}
}
Iterator.h
// Template CLASS PROVIDED: Iterator
#pragma once
#include "Node.h"
namespace list_1
{
template<typename T>
class Iterator
{
public:
Iterator<T> (Node<T> *np);
// precondition: is_item is true
// post condition n points to the next item in the list
void operator++();
// precondition:
// postcondition: returns true if there is a valid item
bool is_item();
// precondition: is_item == true
// postcondition returns data that n is pointing at
T operator* ();
private:
Node<T>* n;
};
List.h
#ifndef LIST_H
#define LIST_H
#include "Node.h"
#include "Iterator.h"
namespace list_1
{
template <typename T>
class list
{
public:
// CONSTRUCTOR
list( );
// postcondition: all nodes in the list are destroyed.
~list();
// MODIFICATION MEMBER FUNCTIONS
//postcondition: entry is added to the front of the list
void insert_front(const T& entry);
//postcondition: entry is added to the back of the list
void add_back(const T& entry);
// postcondition: all nodes with data == entry are removed from the list
void remove_all(const T& entry);
// postcondition: an iterator is created pointing to the head of the list
Iterator<T> begin(void);
// CONSTANT MEMBER FUNCTIONS
// postcondition: the size of the list is returned
int size( ) const;
private:
Node<T>* head;
};
Your syntax errors are because you are missing a couple closing curly brackets on your "else" blocks at the end of the remove_all function.
Try replacing it with this
(edit: included the suggestion about cout mentioned in the comments above)
void list<T>::remove_all(const T& entry)
{
if(head == 0)
{
std::cout<<" node cannot be delted";
}
else
{
Node<T> *curr = head;
Node<T> *trail = 0;
while( curr != 0)
{
if(curr->entry == entry)
{
break;
}
else
{
trail = curr;
curr = curr->next;
}
}
if(curr == 0)
{
std::cout<<" Node " << entry<< " is not found";
}
else
{
if ( head == curr)
{
head = head->next;
}
else
{
trail->next = curr->next;
}
} // missing this one
delete curr;
} // and this one as well
}

Generic binary tree node destructor issue

I've been working on an assignment and now I'm stuck with buggy destructors. I have to create a generic binary tree with all the usual member functions and some special operators. There's also a restriction: everything must work iteratively so no nasty recursive hacks this time.
There is obviously something very wrong with the destructor of BinTreeNode class because if I delete the node like this:
BinTreeNode<int> * node = new BinTreeNode<int>();
delete node;
I can still access its data:
node->getData(); //should fail miserably
so deletion has no effect but I have no usable idea how I should correct the destructor.
It seems to me that the algorithm should be about right so I suspect there's something wrong with how I use pointers but at this point I'm so confused that I don't even understand my own code.
Code I have this far:
BinTree.h
#ifndef BINTREE_H_
#define BINTREE_H_
#ifndef NULL
#define NULL 0
#endif
#include "BinTreeNode.h"
template <class T>
class BinTree
{
private:
BinTreeNode<T> * root;
public:
//constructors and destructor
BinTree():
root(NULL){}
BinTree(T data):
root(new BinTreeNode<T>(data)){}
~BinTree();
//search
BinTreeNode<T> * search(T data);
//insert
bool insert(T data);
//remove
bool remove(T data);
};
template <class T>
BinTree<T>::~BinTree()
{
delete root;
}
template <class T>
BinTreeNode<T> * BinTree<T>::search(T data)
{
BinTreeNode<T> * node = new BinTreeNode<T>(data);
BinTreeNode<T> * current = root;
while (current != NULL)
{
if (*current == *node)
{
delete node;
return root;
}
else if (*node < *current)
{
current = current->getLeft();
}
else
{
current = current->getRight();
}
}
delete node;
return NULL;
}
template <class T>
bool BinTree<T>::insert(T data)
{
BinTreeNode<T> * node = new BinTreeNode<T>(data);
BinTreeNode<T> * current = root;
while (current != NULL)
{
if (*current == *node)
{
delete node;
return false;
}
else if (*node < *current)
{
if (current->getLeft() == NULL)
{
current->setLeft(node);
return true;
}
else
{
current = current->getLeft();
}
}
else
{
if (current->getRight() == NULL)
{
current->setRight(node);
return true;
}
else
{
current = current->getRight();
}
}
}
return false;
}
#endif
BinTreeNode.h
#ifndef BINTREENODE_H_
#define BINTREENODE_H_
#ifndef NULL
#define NULL 0
#endif
template <class T>
class BinTreeNode
{
private:
T data;
BinTreeNode<T> *left, *right, *parent;
public:
//constructors and destructor
BinTreeNode():
data(NULL), left(NULL), right(NULL), parent(NULL){}
BinTreeNode(T data):
data(data), left(NULL), right(NULL), parent(NULL){}
~BinTreeNode();
//set and get data member
T getData() const;
void setData(T data);
//set and get left and right branches
BinTreeNode<T> * getLeft() const;
BinTreeNode<T> * getRight() const;
void setLeft(BinTreeNode<T> * node);
void setRight(BinTreeNode<T> * node);
//set and get parent
BinTreeNode<T> * getParent() const;
void setParent(BinTreeNode<T> * node);
//comparison operators
bool operator<(const BinTreeNode<T>& node) const;
bool operator>(const BinTreeNode<T>& node) const;
bool operator==(const BinTreeNode<T>& node) const;
};
template <class T>
BinTreeNode<T>::~BinTreeNode()
{
BinTreeNode<T> * current = this;
BinTreeNode<T> * parent = NULL;
while (current != NULL)
{
parent = current->getParent();
if (current->getLeft() == NULL)
current = current->getLeft();
else if (current->getRight() == NULL)
current = current->getRight();
else
{
if (parent->getRight() == current)
parent->setRight(NULL);
else
parent->setLeft(NULL);
current = NULL; // this line (among others) is very suspicious
}
current = parent;
}
}
template <class T>
T BinTreeNode<T>::getData() const
{
return data;
}
template <class T>
void BinTreeNode<T>::setData(T data)
{
this->data = data;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getLeft() const
{
return left;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getRight() const
{
return right;
}
template <class T>
void BinTreeNode<T>::setLeft(BinTreeNode<T> * node)
{
node->setParent(this);
left = node;
}
template <class T>
void BinTreeNode<T>::setRight(BinTreeNode<T> * node)
{
node->setParent(this);
right = node;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getParent() const
{
return parent;
}
template <class T>
void BinTreeNode<T>::setParent(BinTreeNode<T> * node)
{
parent = node;
}
template <class T>
bool BinTreeNode<T>::operator<(const BinTreeNode<T>& node) const
{
return this->data < node.data;
}
template <class T>
bool BinTreeNode<T>::operator>(const BinTreeNode<T>& node) const
{
return this->data > node.data;
}
template <class T>
bool BinTreeNode<T>::operator==(const BinTreeNode<T>& node) const
{
return this->data == node.data;
}
#endif /* BINTREENODE_H_ */
Your BinTreeNode destructor should simply be:
template <class T>
BinTreeNode<T>::~BinTreeNode() {
delete left;
delete right;
}
That will call left and right's destructors recursively, freeing the memory allocated for those nodes and their child nodes. This will as a consequence free the entire tree.
Assigning NULL to a pointer does not free the memory pointed by it.
On the other hand, what you mention, that after deletion, this line:
node->getData();
Still returns data, is perfectly normal. Deletion frees the memory, but the data stored in it might still be available for a while, until something new is written in that memory address. Accessing an already free'd memory address implies undefined behaviour.
BTW, you should use "0"(without quotes) in C++ instead of NULL. Therefore, there it's not necessary to use the #ifndef NULL(...).
EDIT: I hadn't seen the "no recursion" comment. Here's a non-recursive algorithm:
#include <deque>
/* ... */
template <class T>
BinTreeNode<T>::~BinTreeNode() {
std::deque deq;
// we're going to delete our children
deq.push_back(this);
while(deq.size()) {
BinTreeNode<T> *ptr = deq.front();
deq.pop_front();
if(ptr) {
deq.push_back(ptr->left);
deq.push_back(ptr->right);
// we don't want the child nodes
// to double delete the children
ptr->left = 0;
ptr->right = 0;
// avoid deleteing ourselves
if(ptr != this)
delete ptr;
}
}
}
I haven't tested it, but it should work.