My problem is trying to get functions treeLeavesCount() and treeNodeCount() to return a value of leaves and nodes in the tree but, my issue is after providing values through a while loop using an insert() function, the tree seems to stay empty and I know this by using an isEmpty() function before and after inserting values into the tree.
main.cpp
#include <iostream>
#include "binaryTreeType.h"
#include "bSearchTreeType.h"
using namespace std;
int main()
{
int num;
bSearchTreeType<int> *myTree= new bSearchTreeType<int>();
//test if tree is empty
if(myTree->isEmpty())
cout << "yes" << endl;
else
cout << "no" << endl;
cout << "Line 10: Enter numbers ending with -999"<< endl;
cin >> num;
while (num != -999)
{
myTree->insert(num);
cin >> num;
}
myTree->inorderTraversal();
int p;
p=myTree->treeNodeCount();
cout << p << endl;
p=myTree->treeLeavesCount();
cout << p << endl;
//test if tree is empty after data is inserted
if(myTree->isEmpty())
cout << "yes" << endl;
else
cout << "no" << endl;
delete myTree;
return 0;
}
binaryTreeType.h
#ifndef BINARYTREETYPE_H
#define BINARYTREETYPE_H
#include <queue>
template <class elemType>
struct binaryTreeNode
{
elemType info;
binaryTreeNode<elemType> *llink;
binaryTreeNode<elemType> *rlink;
};
template <class elemType>
class binaryTreeType
{
public:
const binaryTreeType<elemType>& operator=(const binaryTreeType<elemType>&);
//Overload the assignment operator.
bool isEmpty() const;
//Returns true if the binary tree is empty;
//otherwise, returns false.
void inorderTraversal() const;
//Function to do an inorder traversal of the binary tree.
void preorderTraversal() const;
//Function to do a preorder traversal of the binary tree.
void postorderTraversal() const;
//Function to do a postorder traversal of the binary tree.
int treeHeight() const;
//Returns the height of the binary tree.
int treeNodeCount() const;
//Returns the number of nodes in the binary tree.
int treeLeavesCount() const;
//Returns the number of leaves in the binary tree.
void destroyTree();
//Deallocates the memory space occupied by the binary tree.
//Postcondition: root = NULL;
binaryTreeType(const binaryTreeType<elemType>& otherTree);
//copy constructor
binaryTreeType();
//default constructor
~binaryTreeType();
//destructor
protected:
binaryTreeNode<elemType> *root;
private:
void copyTree(binaryTreeNode<elemType>* &copiedTreeRoot,binaryTreeNode<elemType>* otherTreeRoot);
//Makes a copy of the binary tree to which
//otherTreeRoot points. The pointer copiedTreeRoot
//points to the root of the copied binary tree.
void destroy(binaryTreeNode<elemType>* &p);
//Function to destroy the binary tree to which p points.
//Postcondition: p = NULL
void inorder(binaryTreeNode<elemType> *p) const;
//Function to do an inorder traversal of the binary
//tree to which p points.
void preorder(binaryTreeNode<elemType> *p) const;
//Function to do a preorder traversal of the binary
//tree to which p points.
void postorder(binaryTreeNode<elemType> *p) const;
//Function to do a postorder traversal of the binary
//tree to which p points.
int height(binaryTreeNode<elemType> *p) const;
//Function to return the height of the binary tree
//to which p points.
int max(int x, int y) const;
//Returns the larger of x and y.
int nodeCount(binaryTreeNode<elemType> *p) const;
//Function to return the number of nodes in the binary
//tree to which p points
int leavesCount(binaryTreeNode<elemType> *p) const;
//Function to return the number of leaves in the binary
//tree to which p points
};
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
};
template <class elemType>
binaryTreeType<elemType>::binaryTreeType()
{
root = NULL;
}
template <class elemType>
void binaryTreeType<elemType>::inorderTraversal() const
{
inorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::preorderTraversal() const
{
preorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::postorderTraversal() const
{
postorder(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeHeight() const
{
return height(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount() const
{
return nodeCount(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeLeavesCount() const
{
return leavesCount(root);
}
template <class elemType>
void binaryTreeType<elemType>::inorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
inorder(p->llink);
std::cout << p->info << " ";
inorder(p->rlink);
}
}
template <class elemType>
void binaryTreeType<elemType>::preorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
std::cout << p->info << " ";
preorder(p->llink);
preorder(p->rlink);
}
}
template <class elemType>
void binaryTreeType<elemType>::postorder(binaryTreeNode<elemType> *p) const
{
if (p != NULL)
{
postorder(p->llink);
postorder(p->rlink);
std::cout << p->info << " ";
}
}
template <class elemType>
int binaryTreeType<elemType>::height(binaryTreeNode<elemType> *p) const
{
if (p == NULL)
return 0;
else
return 1 + max(height(p->llink), height(p->rlink));
}
template <class elemType>
int binaryTreeType<elemType>::max(int x, int y) const
{
if (x >= y)
return x;
else
return y;
}
template <class elemType>
void binaryTreeType<elemType>::copyTree(binaryTreeNode<elemType>* &copiedTreeRoot,binaryTreeNode<elemType>* otherTreeRoot)
{
if (otherTreeRoot == NULL)
copiedTreeRoot = NULL;
else
{
copiedTreeRoot = new binaryTreeNode<elemType>;
copiedTreeRoot->info = otherTreeRoot->info;
copyTree(copiedTreeRoot->llink, otherTreeRoot->llink);
copyTree(copiedTreeRoot->rlink, otherTreeRoot->rlink);
}
} //end copyTree
template <class elemType>
void binaryTreeType<elemType>::destroy(binaryTreeNode<elemType>* &p)
{
if (p != NULL)
{
destroy(p->llink);
destroy(p->rlink);
delete p;
p = NULL;
}
}
template <class elemType>
void binaryTreeType<elemType>::destroyTree()
{
destroy(root);
}
template <class elemType>
binaryTreeType<elemType>::binaryTreeType(const binaryTreeType<elemType>& otherTree)
{
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}
template <class elemType>
binaryTreeType<elemType>::~binaryTreeType()
{
destroy(root);
}
template <class elemType>
const binaryTreeType<elemType>& binaryTreeType<elemType>::operator=(const binaryTreeType<elemType>& otherTree)
{
if (this != &otherTree) //avoid self-copy
{
if (root != NULL) //if the binary tree is not empty,
//destroy the binary tree
destroy(root);
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}//end else
return *this;
}
template <class elemType>
int binaryTreeType<elemType>::leavesCount(binaryTreeNode<elemType> *p) const
{
if(p == NULL)
return 0;
if(p->llink == NULL && p->rlink==NULL)
return 1;
else
return leavesCount(p->llink) + leavesCount(p->rlink);
}
template <class elemType>
int binaryTreeType<elemType> ::nodeCount(binaryTreeNode<elemType> *p) const
{
int count = 1;
if ( p == NULL ){
return 0;
}else{
count += nodeCount(p->llink);
count += nodeCount(p->rlink);
}
return count;
}
#endif // BINARYTREETYPE_H
bSearchTreeType.h
#ifndef BSEARCHTREETYPE_H
#define BSEARCHTREETYPE_H
#include "binaryTreeType.h"
#include <iostream>
#include <cassert>
template <class elemType>
class bSearchTreeType : public binaryTreeType<elemType>
{
public:
bool search(const elemType& searchItem) const;
//Function to determine if searchItem is in the binary
//search tree.
//Postcondition: Returns true if searchItem is found in the
// binary search tree; otherwise, returns false.
void insert(const elemType& insertItem);
//Function to insert insertItem in the binary search tree.
//Postcondition: If no node in the binary search tree has the
// same info as insertItem, a node with the info insertItem
// is created and inserted in the binary search tree.
void deleteNode(const elemType& deleteItem);
//Function to delete deleteItem from the binary search tree.
//Postcondition: If a node with the same info as deleteItem
// is found, it is deleted from the binary search tree.
protected:
binaryTreeNode<elemType> *root;
private:
void deleteFromTree(binaryTreeNode<elemType>* &p);
//Function to delete the node to which p points is deleted
//from the binary search tree.
//Postcondition: The node to which p points is deleted from
// the binary search tree.
};
using namespace std;
template <class elemType>
bool bSearchTreeType<elemType>::search(const elemType& searchItem) const
{
binaryTreeNode<elemType> *current;
bool found = false;
if (root == NULL)
cerr << "Cannot search the empty tree." << endl;
else
{
current = root;
while (current != NULL && !found)
{
if (current->info == searchItem)
found = true;
else if (current->info > searchItem)
current = current->llink;
else
current = current->rlink;
}//end while
}//end else
return found;
}//end search
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
binaryTreeNode<elemType> *current; //pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *newNode; //pointer to create the node
newNode = new binaryTreeNode<elemType>;
assert(newNode != NULL);
newNode->info = insertItem;
newNode->llink = NULL;
newNode->rlink = NULL;
if (root == NULL)
root = newNode;
else
{
current = root;
while (current != NULL)
{
trailCurrent = current;
if (current->info == insertItem)
{
std::cerr << "The insert item is already in the list-";
std::cerr << "duplicates are not allowed." << insertItem << std::endl;
return;
}
else if (current->info > insertItem)
current = current->llink;
else
current = current->rlink;
}//end while
if (trailCurrent->info > insertItem)
trailCurrent->llink = newNode;
else
trailCurrent->rlink = newNode;
}
}//end insert
template <class elemType>
void bSearchTreeType<elemType>::deleteFromTree(binaryTreeNode<elemType>* &p)
{
binaryTreeNode<elemType> *current;//pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
binaryTreeNode<elemType> *temp; //pointer to delete the node
if (p == NULL)
cerr << "Error: The node to be deleted is NULL." << endl;
else if(p->llink == NULL && p->rlink == NULL)
{
temp = p;
p = NULL;
delete temp;
}
else if(p->llink == NULL)
{
temp = p;
p = temp->rlink;
delete temp;
}
else if(p->rlink == NULL)
{
temp = p;
p = temp->llink;
delete temp;
}
else
{
current = p->llink;
trailCurrent = NULL;
while (current->rlink != NULL)
{
trailCurrent = current;
current = current->rlink;
}//end while
p->info = current->info;
if (trailCurrent == NULL) //current did not move;
//current == p->llink; adjust p
p->llink = current->llink;
else
trailCurrent->rlink = current->llink;
delete current;
}//end else
}//end deleteFromTree
template <class elemType>
void bSearchTreeType<elemType>::deleteNode(const elemType& deleteItem)
{
binaryTreeNode<elemType> *current; //pointer to traverse the tree
binaryTreeNode<elemType> *trailCurrent; //pointer behind current
bool found = false;
if (root == NULL)
std::cout << "Cannot delete from the empty tree." << endl;
else
{
current = root;
trailCurrent = root;
while (current != NULL && !found)
{
if (current->info == deleteItem)
found = true;
else
{
trailCurrent = current;
if (current->info > deleteItem)
current = current->llink;
else
current = current->rlink;
}
}//end while
if (current == NULL)
std::cout << "The delete item is not in the tree." << endl;
else if (found)
{
if (current == root)
deleteFromTree(root);
else if (trailCurrent->info > deleteItem)
deleteFromTree(trailCurrent->llink);
else
deleteFromTree(trailCurrent->rlink);
}//end if
}
}//end deleteNode
#endif // BSEARCHTREETYPE_H
(That's a humongous amount of code. Please remove everything your test case doesn't need next time.)
Cutting your code down to the bare essentials, we get
template <class elemType>
class binaryTreeType
{
public:
bool isEmpty() const;
protected:
binaryTreeNode<elemType> *root;
};
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
};
template <class elemType>
class bSearchTreeType : public binaryTreeType<elemType>
{
void insert(const elemType& insertItem);
protected:
binaryTreeNode<elemType> *root;
};
template <class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
// ...
if (root == NULL)
root = newNode;
else
{
current = root;
//...
}
}//end insert
And now we can see that you declare two member variables called "root".
The one in bSearchTreeType hides the one in binaryTreeType - it's not a redeclaration or "override" of the same variable.
This means that your binaryTreeType member functions (such as isEmpty) use the root in binaryTreeType, while the member functions of bSearchTreeType (such as insert) use the root in bSearchTreeType, so after insert has updated one of the roots the other one is still null.
Incidentally, this issue is also difficult to discover with a debugger, where you'll just be staring at a variable whose value changes as if by magic.
You need to do two things:
Remove the root member from bSearchTreeType
Because these are templates, you also need to change root to this->root in the bSearchTreeType member functions. (Finding out why left as an exercise - it's an essay of its own.)
(It seems to work with just these changes, by the way. Well done.)
Related
Hi I having problem when I try to implement my delete tree function in my Bst class. This is what i have implemented. Currently only have the insert and deletetree functions.
struct nodeType
{
int data;
nodeType * LeftLink;
nodeType * RightLink;
};
class Bst
{
public:
/**
* Default constructor
*/
Bst();
~Bst();
bool isEmpty() const;
void Insert(int insertItem);
void Destroy(nodeType* &p);
void DeleteTree();
bool Search(int searchItem);
void inOrderTraversal() const;
void preOrderTraversal() const;
void postOrderTraversal() const;
void inOrderTraversal(void(*visit) (int& item)) const;
private:
nodeType * root;
void inOrder(nodeType *p, void(*visit) (int &item)) const;
};
Bst::Bst()
{
root = nullptr;
}
Bst::~Bst()
{
Destroy(root);
}
bool Bst::isEmpty() const
{
return (root == nullptr);
}
void Bst::Insert(int insertItem)
{
nodeType* NewNode = new nodeType;
nodeType* trailCurrent = nullptr;
nodeType* current;
NewNode->data = insertItem;
NewNode->LeftLink = NULL;
NewNode->RightLink = NULL;
if(root == NULL)
{
root = NewNode;
}
else
{
current = root;
while(current != nullptr)
{
trailCurrent = current;
if(insertItem == current->data)
{
cout << "item already inserted, No duplicates allowed." << endl;
return;
}
else if(insertItem > current->data)
{
current = current->RightLink;
}
else
{
current = current->LeftLink;
}
}//endwhile
if(insertItem > trailCurrent->data)
{
trailCurrent->RightLink = NewNode;
cout << NewNode->data << " Inserted" << endl;
}
else
{
trailCurrent->LeftLink = NewNode;
cout << NewNode->data << " Inserted" << endl;
}
}
}
//Delete tree function
void Bst::Destroy(nodeType * &p)
{
if(p != NULL)
{
Destroy(p->LeftLink);
Destroy(p->RightLink);
delete p;
p = NULL;
}
}
void Bst::DeleteTree()
{
Destroy(root);
}
main
int main()
{
Bst intTree;
intTree.Insert(5);
intTree.Insert(3);
intTree.Insert(7);
intTree.Insert(10);
intTree.DeleteTree();
cout << "is tree empty: " << intTree.isEmpty() << endl;
}
When i try to call the DeleteTree function my programs ends without printing out the "is tree empty:" line and ends with Process returned -1073741571 (0xC00000FD).
Can anyone figure out what is happening?
EDIT::
Thanks for all the help! I have changed the insert function as it looks like I was doing the inserting wrongly. I have updated my code to the corrected version.
Yet again thanks for the help.
Please edit as follows:
while(current != nullptr)
{
trailCurrent = current;
if(current->data == insertItem)
{
cout << "item already inserted, No duplicates allowed." << endl;
return;
}
else if(current->data > insertItem)
{
current = current->RightLink;
}
else
{
current = current->LeftLink;
}
}
if(trailCurrent->data > insertItem)
{
trailCurrent->LeftLink = NewNode;
}
else
trailCurrent->RightLink = NewNode;
The problem is not with your DeleteTree method. Instead the Insert method is inserting same node at multiple places which is causing issue of dangling pointers because when two or more pointers point to single node and one is deleted then the other is pointing to a deleted node and that causes the crash when we try to access it.
Here is a simplified version of insert. This fixes the issue, although I am not sure if that is your intended implementation requirement.
class Bst
{
public:
Bst();
bool isEmpty() const;
nodeType* Insert(int insertItem, nodeType *tmpRoot=NULL);
void Destroy(nodeType*& p);
void DeleteTree();
bool Search(int searchItem);
void inOrderTraversal() const;
void preOrderTraversal() const;
void postOrderTraversal() const;
private:
nodeType* root;
};
nodeType* Bst::Insert(int insertItem, nodeType* tmpRoot)
{
nodeType* NewNode = new nodeType;
NewNode->data = insertItem;
NewNode->LeftLink = NewNode->RightLink = nullptr;
if (tmpRoot == nullptr)
{
tmpRoot = NewNode;
if (root == nullptr)
root = tmpRoot;
}
else
{
if (tmpRoot->data == insertItem)
{
cout << "item already inserted, No duplicates allowed." << endl;
return tmpRoot;
}
else if (tmpRoot->data > insertItem)
{
tmpRoot->LeftLink = Insert(insertItem, tmpRoot->LeftLink);
}
else
{
tmpRoot->RightLink = Insert(insertItem, tmpRoot->RightLink);
}
}
return tmpRoot;
}
After updating this code it should work just fine.
I am having an issue with a homework assignment and for the life of me I cannot figure out where I am making the mistake. We are tasked with writing a function that inserts the nodes of binary tree into an ordered linked list. Below are the header files and the main method. Literally any help at this point would greatly appreciated as I am just spinning in circles now.
Error Message: no suitable conversion function from "orderedLinkedList" to "const int" exists
Project: Ch19_Ex9 File: Ch19_Ex9.cpp Line: 33:
Ch19_Ex9.cpp:
//Data
//68 43 10 56 77 82 61 82 33 56 72 66 99 88 12 6 7 21 -999
#include "binarySearchTree.h"
#include "orderedLinkedList.h"
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
binarySearchTree<int> treeRoot;
orderedLinkedList<int> newList;
int num;
cout << "Enter numbers ending with -999" << endl;
cin >> num;
while (num != -999)
{
treeRoot.insert(num);
cin >> num;
}
cout << endl << "Tree nodes in inorder: ";
treeRoot.inorderTraversal();
cout << endl;
cout << "Tree Height: " << treeRoot.treeHeight()
<< endl;
treeRoot.createList(newList); //HERE IS THE LINE WITH ISSUE
cout << "newList: ";
newList.print();
cout << endl;
system("pause");
return 0;
}
binarySearchTree.h:
//Header File Binary Search Tree
#include <iostream>
#include "binaryTree.h"
using namespace std;
template <class Type>
class binarySearchTree : public binaryTreeType<Type>
{
public:
bool search(const Type& searchItem) const;
//Function to determine if searchItem is in the binary
//search tree.
//Postcondition: Returns true if searchItem is found in
// the binary search tree; otherwise,
// returns false.
void insert(const Type& insertItem);
//Function to insert insertItem in the binary search tree.
//Postcondition: If there is no node in the binary search
// tree that has the same info as
// insertItem, a node with the info
// insertItem is created and inserted in the
// binary search tree.
void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the binary search tree
//Postcondition: If a node with the same info as deleteItem
// is found, it is deleted from the binary
// search tree.
// If the binary tree is empty or deleteItem
// is not in the binary tree, an appropriate
// message is printed.
void createList(const Type& addItem);
private:
void deleteFromTree(nodeType<Type>* &p);
//Function to delete the node to which p points is
//deleted from the binary search tree.
//Postcondition: The node to which p points is deleted
// from the binary search tree.
};
template <class Type>
bool binarySearchTree<Type>::search
(const Type& searchItem) const
{
nodeType<Type> *current;
bool found = false;
if (root == nullptrptr)
cout << "Cannot search an empty tree." << endl;
else
{
current = root;
while (current != nullptrptr && !found)
{
if (current->info == searchItem)
found = true;
else if (current->info > searchItem)
current = current->lLink;
else
current = current->rLink;
}//end while
}//end else
return found;
}//end search
template <class Type>
void binarySearchTree<Type>::insert
(const Type& insertItem)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
nodeType<Type> *newNode; //pointer to create the node
newNode = new nodeType<Type>;
newNode->info = insertItem;
newNode->lLink = nullptrptr;
newNode->rLink = nullptrptr;
if (root == nullptrptr)
root = newNode;
else
{
current = root;
while (current != nullptrptr)
{
trailCurrent = current;
if (current->info == insertItem)
{
cout << "The item to be inserted is already ";
cout << "in the tree -- duplicates are not "
<< "allowed." << endl;
return;
}
else if (current->info > insertItem)
current = current->lLink;
else
current = current->rLink;
}//end while
if (trailCurrent->info > insertItem)
trailCurrent->lLink = newNode;
else
trailCurrent->rLink = newNode;
}
}//end insert
template <class Type>
void binarySearchTree<Type>::deleteNode
(const Type& deleteItem)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
bool found = false;
if (root == nullptr)
cout << "Cannot delete from an empty tree."
<< endl;
else
{
current = root;
trailCurrent = root;
while (current != nullptr && !found)
{
if (current->info == deleteItem)
found = true;
else
{
trailCurrent = current;
if (current->info > deleteItem)
current = current->lLink;
else
current = current->rLink;
}
}//end while
if (current == nullptr)
cout << "The item to be deleted is not in the tree."
<< endl;
else if (found)
{
if (current == root)
deleteFromTree(root);
else if (trailCurrent->info > deleteItem)
deleteFromTree(trailCurrent->lLink);
else
deleteFromTree(trailCurrent->rLink);
}
else
cout << "The item to be deleted is not in the tree."
<< endl;
}
} //end deleteNode
template <class Type>
void binarySearchTree<Type>::deleteFromTree
(nodeType<Type>* &p)
{
nodeType<Type> *current; //pointer to traverse the tree
nodeType<Type> *trailCurrent; //pointer behind current
nodeType<Type> *temp; //pointer to delete the node
if (p == nullptr)
cout << "Error: The node to be deleted does not exist."
<< endl;
else if (p->lLink == nullptr && p->rLink == nullptr)
{
temp = p;
p = nullptr;
delete temp;
}
else if (p->lLink == nullptr)
{
temp = p;
p = temp->rLink;
delete temp;
}
else if (p->rLink == nullptr)
{
temp = p;
p = temp->lLink;
delete temp;
}
else
{
current = p->lLink;
trailCurrent = nullptr;
while (current->rLink != nullptr)
{
trailCurrent = current;
current = current->rLink;
}//end while
p->info = current->info;
if (trailCurrent == nullptr) //current did not move;
//current == p->lLink; adjust p
p->lLink = current->lLink;
else
trailCurrent->rLink = current->lLink;
delete current;
}//end else
} //end deleteFromTree
template <class Type>
void binarySearchTree<Type>::createList(const Type& addItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
nodeType<Type> *newNode;
newNode = new nodeType <Type>;
newNode->info = createItem;
newNode->lLink = nullptr;
newNode->rLink = nullptr;
if (root == nullptr)
{
root = newNode;
}
}
EDIT: adding orderedLinkedList.h:
#include "linkedList.h"
using namespace std;
template <class Type>
class orderedLinkedList : public linkedListType<Type>
{
public:
bool search(const Type& searchItem) const;
void insert(const Type& newItem);
void insertFirst(const Type& newItem);
void insertLast(const Type& deleteItem);
void deleteNode(const Type& deleteItem);
};
template <class Type>
bool orderedLinkedList<Type>::search(const Type& searchItem) const
{
nodeType<Type> *current; //pointer to traverse the list
bool found = false;
current = first; //set current to point to the first
//node in the list
while (current != nullptr && !found) //search the list
if (current->info == searchItem) //searchItem is found
found = true;
else
current = current->link; //make current point to
//the next node
return found;
};
template <class Type>
void orderedLinkedList<Type>::insert(const Type& newItem)
{
};
template <class Type>
void orderedLinkedList<Type>::insertFirst(const Type& newItem)
{
nodeType<Type> *newNode; //pointer to create the new node
newNode = new nodeType<Type>; //create the new node
newNode->info = newItem; //store the new item in the node
newNode->link = first; //insert newNode before first
first = newNode; //make first point to the
//actual first node
count++; //increment count
if (last == nullptr) //if the list was empty, newNode is also
//the last node in the list
last = newNode;
};
template <class Type>
void orderedLinkedList<Type>::insertLast(const Type& deleteItem)
{
nodeType<Type> *newNode; //pointer to create the new node
newNode = new nodeType<Type>; //create the new node
newNode->info = newItem; //store the new item in the node
newNode->link = nullptr; //set the link field of newNode
//to nullptr
if (first == nullptr) //if the list is empty, newNode is
//both the first and last node
{
first = newNode;
last = newNode;
count++; //increment count
}
else //the list is not empty, insert newNode after last
{
last->link = newNode; //insert newNode after last
last = newNode; //make last point to the actual
//last node in the list
count++; //increment count
}
};
template <class Type>
void orderedLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current;
nodeType<Type> *trailCurrent;
bool found;
if (first == nullptr)
{
cout << "Cannot delete from an empty list."
<< endl;
}
else
{
if (first->info == deleteItem)
{
current = first;
first = first->link;
count--;
if (first == nullptr)
{
last = nullptr;
delete current;
}
else
{
found = false;
trailCurrent = first;
current = first->link;
while (current != nullptr && !found)
{
if (current->info != deleteItem)
{
trailCurrent = current;
current = current->link;
}
else
{
found = true;
}
}
if (found)
{
trailCurrent->link = current->link;
count--;
if (last == current)
{
last = trailCurrent;
}
delete current;
}
else
cout << "The item to be deleted is not in "
<< "the list." << endl;
}
}
}
}
I am trying to write this program for homework, and it wasn't throwing the C2259 error until I added the createList function.
I can't figure out where this problem is originating from. I am fairly new at c++ so this might be an easy fix, but I am completely lost.
Here is my main function:
#include <iostream>
#include "binarySearchTree.h"
#include "orderedLinkedList.h"
using namespace std;
int main()
{
bSearchTreeType<int> treeRoot; //error C2259: 'bSearchTreeType<int>'
//cannot instantiate abstract class
orderedLinkedList<int> newList;
int num;
cout << "Enter numbers ending with -999" << endl;
cin >> num;
while (num != -999)
{
treeRoot.insert(num);
cin >> num;
}
cout << endl << "Tree nodes in inorder: ";
treeRoot.inorderTraversal();
cout << endl;
cout << "Tree Height: " << treeRoot.treeHeight()
<< endl;
treeRoot.createList(newList);
cout << "newList: ";
newList.print();
cout << endl;
system("pause");
return 0;
}
Here is binarySearchTree.h:
//Header File Binary Search Tree
#ifndef H_binarySearchTree
#define H_binarySearchTree
#include <iostream>
#include"binaryTree.h"
using namespace std;
template<class elemType>
class bSearchTreeType : public binaryTreeType < elemType >
{
public:
//function to determine if searchItem is in search tree
bool search(const elemType& searchItem) const;
void insert(const elemType& insertItem);
void deleteNode(const elemType& deleteItem);
//update: void createList(const elemType& createItem);
virtual void createList(const elemType& newList) = 0;
private:
void deleteFromTree(nodeType<elemType> *&p);
};
template<class elemType>
void bSearchTreeType<elemType>::createList(const elemType& createItem)
{
nodeType<elemType> *current;
nodeType<elemType> *trailCurrent;
nodeType<elemType> *newNode;
newNode = new nodeType < elemType > ;
newNode->info = createItem;
newNode->lLink = nullptr;
newNode->rLink = nullptr;
if (root == nullptr)
{
root = newNode;
}
}
template<class elemType>
bool bSearchTreeType<elemType>::search(const elemType& searchItem)const
{
nodeType<elemType> *current;
bool found = false;
if (root == NULL)
{
cout << "Cannot search an empty tree." << endl;
}
else
{
current = root;
while (current != NULL && !found)
{
if (current->info == searchItem)
{
found = true;
}
else if (current->info > searchItem)
{
current = current->lLink;
}
else
{
current = current->rLink;
}
}
}
return found;
}
template<class elemType>
void bSearchTreeType<elemType>::insert(const elemType& insertItem)
{
nodeType<elemType> *current;
nodeType<elemType> *trailCurrent;
nodeType<elemType> *newNode;
newNode = new nodeType < elemType > ;
newNode->info = insertItem;
newNode->lLink = NULL;
newNode->rLink = NULL;
if (root == NULL)
{
root = newNode;
}
else
{
current = root;
while (current != NULL)
{
trailCurrent = current;
if (current->info == insertItem)
{
cout << "The item to be inserted is already in the tree";
cout << "Duplicates are not allowed." << endl;
return;
}
else if (current->info > insertItem)
{
current = current->lLink;
}
else
{
current = current->rLink;
}
}
if (trailCurrent->info > insertItem)
{
trailCurrent->lLink = newNode;
}
else
{
trailCurrent->rLink = newNode;
}
}
}
template<class elemType>
void bSearchTreeType<elemType>::deleteNode(const elemType& deleteItem)
{
nodeType<elemType> *current;
nodeType<elemType> *trailCurrent;
bool found = false;
if (root == NULL)
{
cout << "Cannot delete from an empty tree." << endl;
}
else
{
current = root;
trailCurrent = root;
while (current != NULL && !found)
{
if (current->info == deleteItem)
{
found = true;
}
else
{
trailCurrent = current;
if (current->info > deleteItem)
{
current = current->lLink;
}
else
{
current = current->rLink;
}
}
}
if (current == NULL)
{
cout << "The item to be deleted is not in the tree." << endl;
}
else if (found)
{
if (current == root)
{
deleteFromTree(root);
}
else if (trailCurrent->info > deleteItem)
{
deleteFromTree(trailCurrent->lLink);
}
else
{
deleteFromTree(trailCurrent->rLink);
}
}
else
{
cout << "The item to be deleted is not in the tree." << endl;
}
}
}
template<class elemType>
void bSearchTreeType<elemType>::deleteFromTree(nodeType<elemType>* &p)
{
nodeType<elemType> *current;
nodeType<elemType> *trailCurrent;
nodeType<elemType> *temp;
if (p == NULL)
{
cout << "Error: The node to be deleted is NULL." << endl;
}
else if (p->lLink == NULL && p->rLink == NULL)
{
temp = p;
p = NULL;
delete temp;
}
else if (p->lLink == NULL)
{
temp = p;
p = temp->rLink;
delete temp;
}
else if (p->rLink == NULL)
{
temp = p;
p = temp->lLink;
delete temp;
}
else
{
current = p->lLink;
trailCurrent = NULL;
while (current->rLink != NULL)
{
trailCurrent = current;
current = current->rLink;
}
p->info = current->info;
if (trailCurrent == NULL)
{
p->lLink = current->lLink;
}
else
{
trailCurrent->rLink = current->lLink;
}
delete current;
}
}
#endif
Also, I am 112% sure my createList function is very wrong and will not create a tree of random numbers, so I could use a little help on that as well.
Update: binaryTree.h definition
#ifndef H_binaryTree
#define H_binaryTree
#include<iostream>
using namespace std;
//Define the node
template<class elemType>
struct nodeType
{
elemType info;
nodeType<elemType> *lLink;
nodeType<elemType> *rLink;
};
template<class elemType>
class binaryTreeType
{
public:
const binaryTreeType<elemType>& operator=(const binaryTreeType<elemType>&);
bool isEmpty() const;
void inorderTraversal() const;
void preorderTraversal() const;
void postorderTraversal() const;
int treeHeight() const;
int treeNodeCount() const;
int treeLeavesCount() const;
void destroyTree();
virtual bool search(const elemType& searchItem) const = 0;
virtual void insert(const elemType& insertItem) = 0;
virtual void deleteNode(const elemType& deleteItem) = 0;
virtual void createList(const elemType& createItem) = 0;
binaryTreeType(const binaryTreeType<elemType>& otherTree);
binaryTreeType();
~binaryTreeType();
protected:
nodeType<elemType> *root;
private:
void copyTree(nodeType<elemType>*& copiedTreeRoot, nodeType<elemType>* otherTreeRoot);
void destroy(nodeType<elemType>* &p);
void inorder(nodeType<elemType> *p)const;
void preorder(nodeType<elemType> *p)const;
void postorder(nodeType<elemType> *p) const;
int height(nodeType<elemType> *p)const;
int max(int x, int y) const;
int nodeCount(nodeType<elemType> *p)const;
int leavesCount(nodeType<elemType> *p)const;
};
template <class elemType>
binaryTreeType<elemType>::binaryTreeType()
{
root = NULL;
}
template <class elemType>
bool binaryTreeType<elemType>::isEmpty() const
{
return (root == NULL);
}
template <class elemType>
void binaryTreeType<elemType>::inorderTraversal() const
{
inorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::preorderTraversal() const
{
preorder(root);
}
template <class elemType>
void binaryTreeType<elemType>::postorderTraversal() const
{
postorder(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeHeight() const
{
return height(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount() const
{
return nodeCount(root);
}
template <class elemType>
int binaryTreeType<elemType>::treeLeavesCount() const
{
return leavesCount(root);
}
template <class elemType>
void binaryTreeType<elemType>::copyTree(nodeType<elemType>* &copiedTreeRoot,
nodeType<elemType>* otherTreeRoot)
{
if (otherTreeRoot == NULL)
copiedTreeRoot = NULL;
else
{
copiedTreeRoot = new nodeType<elemType>;
copiedTreeRoot->info = otherTreeRoot->info;
copyTree(copiedTreeRoot->lLink, otherTreeRoot->lLink);
copyTree(copiedTreeRoot->rLink, otherTreeRoot->rLink);
}
}
template <class elemType>
void binaryTreeType<elemType>::inorder(nodeType<elemType> *p) const
{
if (p != NULL)
{
inorder(p->lLink);
cout << p->info << " ";
inorder(p->rLink);
}
}
template <class elemType>
void binaryTreeType<elemType>::preorder(nodeType<elemType> *p) const
{
if (p != NULL)
{
cout << p->info << " ";
preorder(p->lLink);
preorder(p->rLink);
}
}
template <class elemType>
void binaryTreeType<elemType>::postorder(nodeType<elemType> *p) const
{
if (p != NULL)
{
postorder(p->lLink);
postorder(p->rLink);
cout << p->info << " ";
}
}
//Overload the assignment operator
template <class elemType>
const binaryTreeType<elemType>& binaryTreeType<elemType>::operator=(const binaryTreeType<elemType>& otherTree)
{
if (this != &otherTree) //avoid self-copy
{
if (root != NULL) //if the binary tree is not empty,
//destroy the binary tree
destroy(root);
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}//end else
return *this;
}
template <class elemType>
void binaryTreeType<elemType>::destroy(nodeType<elemType>* &p)
{
if (p != NULL)
{
destroy(p->lLink);
destroy(p->rLink);
delete p;
p = NULL;
}
}
template <class elemType>
void binaryTreeType<elemType>::destroyTree()
{
destroy(root);
}
//copy constructor
template <class elemType>
binaryTreeType<elemType>::binaryTreeType
(const binaryTreeType<elemType>& otherTree)
{
if (otherTree.root == NULL) //otherTree is empty
root = NULL;
else
copyTree(root, otherTree.root);
}
//Destructor
template <class elemType>
binaryTreeType<elemType>::~binaryTreeType()
{
destroy(root);
}
template<class elemType>
int binaryTreeType<elemType>::height
(nodeType<elemType> *p) const
{
if (p == NULL)
return 0;
else
return 1 + max(height(p->lLink), height(p->rLink));
}
template <class elemType>
int binaryTreeType<elemType>::max(int x, int y) const
{
if (x >= y)
return x;
else
return y;
}
template <class elemType>
int binaryTreeType<elemType>::nodeCount(nodeType<elemType> *p) const
{
return nodeCount(root);
}
template <class elemType>
int binaryTreeType<elemType>::leavesCount(nodeType<elemType> *p) const
{
return leavesCount(root);
}
#endif
virtual void createList(const elemType& newList) = 0 ;
/// ~~~~ shouldn't be used in derived class
The pure virtual function should only be present in your abstract class which I assume is binaryTreeType
You have to override createList method since it's a virtual.
Can anyone tell me why my last function height() causes the system to crash? I tested every function and they all work but when I coded this one and called it from main it causes the program to crash. It builds without any errors.
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
using namespace std;
// This class is a template class that creates a binary
// tree that can hold values of any data type. It has
// functions to insert a node, delete a node, display the
// tree In Order, Pre Order and Post Order, search for a
// value, count the number of total nodes, left nodes,
// and a function to determine the height of the tree.
template <class T>
class BinaryTree
{
private:
struct TreeNode
{
T value; // The value in the node
TreeNode *left; // Pointer to left child node
TreeNode *right; // Pointer to right child node
};
TreeNode *root; // Pointer to the root node
// Private member functions
void insert(TreeNode *&, TreeNode *&);
void destroySubTree(TreeNode *);
void deleteNode(T, TreeNode *&);
void makeDeletion(TreeNode *&);
void displayInOrder(TreeNode *) const;
void displayPreOrder(TreeNode *) const;
void displayPostOrder(TreeNode *) const;
int counter(TreeNode *);
int leafCounter(TreeNode *);
int height(TreeNode *);
public:
// Constructor
BinaryTree()
{ root = NULL; }
// Destructor
~BinaryTree()
{ destroySubTree(root); }
// Binary tree operations
void insertNode(T);
bool searchNode(T);
void remove(T);
void displayPreOrder() const
{ displayPreOrder(root); }
void displayInOrder() const
{ displayInOrder(root); }
void displayPostOrder() const
{ displayPostOrder(root); }
// Node counter
int counter()
{
int n = counter(root);
return n;
}
// Leaf counter
int leafCounter()
{
int leaf = leafCounter(root);
return leaf;
}
// Height of the tree
int height()
{
int h = height(root);
return h;
}
};
//*********************************************************
// insert function accepts a TreeNode pointer and a *
// pointer to a node. The function inserts the node into *
// the tree pointer to by the TreeNode pointer. This *
// function is call recursively. *
//*********************************************************
template <class T>
void BinaryTree<T>::insert(TreeNode *&nodePtr, TreeNode *&newNode)
{
if (nodePtr == NULL)
nodePtr = newNode; // Insert the node
else if (newNode->value < nodePtr->value)
insert(nodePtr->left, newNode); // Search the left branch
else
insert(nodePtr->right, newNode);// Search the right branch
}
//*********************************************************
// insertNode creates anew node to hold num as its value *
// and passes it to the insert function. *
//*********************************************************
template <class T>
void BinaryTree<T>::insertNode(T item)
{
TreeNode *newNode; // Pointer to a new node
// Create anew node and store num in it
newNode = new TreeNode;
newNode->value = item;
newNode->left = newNode->right = NULL;
// Insert the node
insert(root, newNode);
}
//**********************************************************
// destroySubTree is called by the destructor. It deletes *
// all nodes in the tree. *
//**********************************************************
template <class T>
void BinaryTree<T>::destroySubTree(TreeNode *nodePtr)
{
if (nodePtr)
{
if (nodePtr->left)
destroySubTree(nodePtr->left);
if (nodePtr->right)
destroySubTree(nodePtr->right);
delete nodePtr;
}
}
//**********************************************************
// searchNode determines if a value is present in the tree.*
// If so, the function returns true. Otherwise it returns *
// false.
//**********************************************************
template <class T>
bool BinaryTree<T>::searchNode(T item)
{
TreeNode *nodePtr = root;
while (nodePtr)
{
if (nodePtr->value == item)
return true;
else if (item < nodePtr->value)
nodePtr = nodePtr->left;
else
nodePtr = nodePtr->right;
}
return false;
}
//*********************************************************
// remove calls deleteNode to delete the node whode value *
// member is the same as num *
//*********************************************************
template <class T>
void BinaryTree<T>::remove(T item)
{
deleteNode(item, root);
}
//*********************************************************
// deleteNode deletes the node whose value member is the *
// same as num *
//*********************************************************
template <class T>
void BinaryTree<T>::deleteNode(T item, TreeNode *&nodePtr)
{
if (item < nodePtr->value)
deleteNode(item, nodePtr->left);
else if (item > nodePtr->value)
deleteNode(item, nodePtr->right);
else
makeDeletion(nodePtr);
}
//*********************************************************
// makeDeletion takes a reference to apointer to the node *
// that is to be deleted. The node is removed and the *
// branches of the tree below the node are reattached *
//*********************************************************
template <class T>
void BinaryTree<T>::makeDeletion(TreeNode *&nodePtr)
{
// Define a temporary pointer to use in reattaching
// the left subtree
TreeNode *tempNodePtr;
if (nodePtr == NULL)
cout << "Cannot delete empty node.\n";
else if (nodePtr->right == NULL)
{
tempNodePtr = nodePtr;
nodePtr = nodePtr->left; // Reattach the left child
delete tempNodePtr;
}
else if (nodePtr->left == NULL)
{
tempNodePtr = nodePtr;
nodePtr = nodePtr->right; // Reattach the right child
delete tempNodePtr;
}
}
//*********************************************************
// The displayInOrder function displays the values in the *
// subtree pointed to by nodePtr, via inorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayInOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
displayInOrder(nodePtr->left);
cout << nodePtr->value << endl;
displayInOrder(nodePtr->right);
}
}
//*********************************************************
// The displayPreOrder function displays the values in the*
// subtree pointed to by nodePtr, via Preorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayPreOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
cout << nodePtr->value << endl;
displayInOrder(nodePtr->left);
displayInOrder(nodePtr->right);
}
}
//*********************************************************
// displayPostOrder function displays the values in the *
// subtree pointed to by nodePtr, via Postorder traversal *
//*********************************************************
template <class T>
void BinaryTree<T>::displayPostOrder(TreeNode *nodePtr) const
{
if (nodePtr)
{
displayInOrder(nodePtr->left);
displayInOrder(nodePtr->right);
cout << nodePtr->value << endl;
}
}
//*********************************************************
// counter counts the number of nodes the tree has *
//*********************************************************
template <class T>
int BinaryTree<T>::counter(TreeNode *nodePtr)
{
if (nodePtr == NULL)
return 0;
else
return counter(nodePtr->left) +1+ counter(nodePtr->right);
}
//*********************************************************
// leafCounter counts the number of leaf nodes in the tree*
//*********************************************************
template <class T>
int BinaryTree<T>::leafCounter(TreeNode *nodePtr)
{
if (nodePtr == NULL)
return 0;
else if (nodePtr->left == NULL && nodePtr->right == NULL)
return 1;
else
return leafCounter(nodePtr->left) + leafCounter(nodePtr->right);
}
//*********************************************************
// height returns the height of the tree *
//*********************************************************
template <class T>
int BinaryTree<T>::height(TreeNode *nodePtr)
{
if(nodePtr = NULL)
return -1;
if (height(nodePtr->left) <= height(nodePtr->right))
return (height(nodePtr->right) +1);
else
return (height(nodePtr->left) +1);
}
#endif
Main
// This program demonstrates that the functions of
// BinaryTree works correctly.
#include "BinaryTree.h"
#include <iostream>
using namespace std;
int main()
{
// Create a BinaryTree object
BinaryTree<int> tree;
// Insert some nodes
cout << "Inserting nodes...\n";
tree.insertNode(5);
tree.insertNode(10);
tree.insertNode(3);
tree.insertNode(1);
tree.insertNode(13);
// Display the nodes InOrder
cout << "\nDisplaying the nodes InOrder...\n";
tree.displayInOrder();
// Display the nodes PreOrder
cout << "\nDisplaying the nodes PreOrder...\n";
tree.displayPreOrder();
// Display the nodes PostOrder
cout << "\nDisplaying the nodes PostOrder...\n";
tree.displayPostOrder();
// Delete a node
cout << "\nDeleting node 3...\n";
tree.remove(3);
// Display the nodes after deletion
cout << "\nHere are the nodes InOrder after deletion:\n";
tree.displayInOrder();
// Search the nodes for the value 10
cout << "\nSearching the nodes for the value 10...\n";
if (tree.searchNode(10))
cout << "Value was found.\n";
else
cout << "Value was not found.\n";
// Search for the deleted node 3
cout << "\nSearching for the deleted node 3...\n";
if (tree.searchNode(3))
cout << "Value was found.\n";
else
cout << "Value was not found.\n";
// Count how many nodes are in the tree
cout << "\nThere are " << tree.counter() << " nodes"
<< " in the tree.\n";
// Count how many leafs are in the tree
cout << "\nThere are " << tree.leafCounter()
<< " leaves in the tree.\n";
// Get the height of the tree
cout << "\nThe height of the tree is " << tree.height();
cout << endl;
return 0;
}
if(nodePtr = NULL)
should be:
if(nodePtr == NULL)
The first one sets nodePtr to NULL, then implicitly tests if the result is not NULL (which is always false). The second one tests whether nodePtr is NULL.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
What is an undefined reference/unresolved external symbol error and how do I fix it?
Again this is a homework assignment and my instructor has given us plenty of feedback but I am still at a lost for this compile issue.
When I place the main function inside the implementation file the program compiles and works perfectly. However when I place the main function into main.cpp the compiler complains:
unresolved external symbol "public: __thiscall doublyLinkedList<int>::doublyLinkedList<int>(void)" (??0?$doublyLinkedList#H##QAE#XZ) referenced in function
Header File
#ifndef H_doublyLinkedList
#define H_doublyLinkedList
#include <iostream>
#include <cassert>
using namespace std;
//Definition of the node
template <class Type>
struct nodeType
{
Type info;
nodeType<Type> *next;
nodeType<Type> *back;
};
template <class Type>
class doublyLinkedList
{
public:
const doublyLinkedList<Type>& operator=
(const doublyLinkedList<Type> &);
//Overload the assignment operator.
void initializeList();
//Function to initialize the list to an empty state.
//Postcondition: first = NULL; last = NULL; count = 0;
bool isEmptyList() const;
//Function to determine whether the list is empty.
//Postcondition: Returns true if the list is empty,
// otherwise returns false.
void destroy();
//Function to delete all the nodes from the list.
//Postcondition: first = NULL; last = NULL; count = 0;
void print() const;
//Function to output the info contained in each node.
void reversePrint() const;
//Function to output the info contained in each node
//in reverse order.
int length() const;
//Function to return the number of nodes in the list.
//Postcondition: The value of count is returned.
Type front() const;
//Function to return the first element of the list.
//Precondition: The list must exist and must not be empty.
//Postcondition: If the list is empty, the program
// terminates; otherwise, the first
// element of the list is returned.
Type back() const;
//Function to return the last element of the list.
//Precondition: The list must exist and must not be empty.
//Postcondition: If the list is empty, the program
// terminates; otherwise, the last
// element of the list is returned.
bool search(const Type& searchItem) const;
//Function to determine whether searchItem is in the list.
//Postcondition: Returns true if searchItem is found in
// the list, otherwise returns false.
void insert(const Type& insertItem);
//Function to insert insertItem in the list.
//Precondition: If the list is nonempty, it must be in
// order.
//Postcondition: insertItem is inserted at the proper place
// in the list, first points to the first
// node, last points to the last node of the
// new list, and count is incremented by 1.
void deleteNode(const Type& deleteItem);
//Function to delete deleteItem from the list.
//Postcondition: If found, the node containing deleteItem
// is deleted from the list; first points
// to the first node of the new list, last
// points to the last node of the new list,
// and count is decremented by 1; otherwise,
// an appropriate message is printed.
doublyLinkedList();
//default constructor
//Initializes the list to an empty state.
//Postcondition: first = NULL; last = NULL; count = 0;
doublyLinkedList(const doublyLinkedList<Type>& otherList);
//copy constructor
~doublyLinkedList();
//destructor
//Postcondition: The list object is destroyed.
public:
int count;
nodeType<Type> *first; //pointer to the first node
nodeType<Type> *last; //pointer to the last node
public:
void copyList(const doublyLinkedList<Type>& otherList);
//Function to make a copy of otherList.
//Postcondition: A copy of otherList is created and
// assigned to this list.
};
#endif
Implementation file:
#include <iostream>
#include <cassert>
#include "doublyLinkedList.h"
using namespace std;
template <class Type>
doublyLinkedList<Type>::doublyLinkedList()
{
first= NULL;
last = NULL;
count = 0;
}
template <class Type>
bool doublyLinkedList<Type>::isEmptyList() const
{
return (first == NULL);
}
template <class Type>
void doublyLinkedList<Type>::destroy()
{
nodeType<Type> *temp; //pointer to delete the node
while (first != NULL)
{
temp = first;
first = first->next;
delete temp;
}
last = NULL;
count = 0;
}
template <class Type>
void doublyLinkedList<Type>::initializeList()
{
destroy();
}
template <class Type>
int doublyLinkedList<Type>::length() const
{
return count;
}
template <class Type>
void doublyLinkedList<Type>::print() const
{
nodeType<Type> *current; //pointer to traverse the list
current = first; //set current to point to the first node
while (current != NULL)
{
cout << current->info << " "; //output info
current = current->next;
}//end while
}//end print
template <class Type>
void doublyLinkedList<Type>::reversePrint() const
{
nodeType<Type> *current; //pointer to traverse
//the list
current = last; //set current to point to the
//last node
while (current != NULL)
{
cout << current->info << " ";
current = current->back;
}//end while
}//end reversePrint
template <class Type>
bool doublyLinkedList<Type>::
search(const Type& searchItem) const
{
bool found = false;
nodeType<Type> *current; //pointer to traverse the list
current = first;
while (current != NULL && !found)
if (current->info >= searchItem)
found = true;
else
current = current->next;
if (found)
found = (current->info == searchItem); //test for
//equality
return found;
}//end search
template <class Type>
Type doublyLinkedList<Type>::front() const
{
assert(first != NULL);
return first->info;
}
template <class Type>
Type doublyLinkedList<Type>::back() const
{
assert(last != NULL);
return last->info;
}
template <class Type>
void doublyLinkedList<Type>::insert(const Type& insertItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
nodeType<Type> *newNode; //pointer to create a node
bool found;
newNode = new nodeType<Type>; //create the node
newNode->info = insertItem; //store the new item in the node
newNode->next = NULL;
newNode->back = NULL;
if(first == NULL) //if the list is empty, newNode is
//the only node
{
first = newNode;
last = newNode;
count++;
}
else
{
found = false;
current = first;
while (current != NULL && !found) //search the list
if (current->info >= insertItem)
found = true;
else
{
trailCurrent = current;
current = current->next;
}
if (current == first) //insert newNode before first
{
first->back = newNode;
newNode->next = first;
first = newNode;
count++;
}
else
{
//insert newNode between trailCurrent and current
if (current != NULL)
{
trailCurrent->next = newNode;
newNode->back = trailCurrent;
newNode->next = current;
current->back = newNode;
}
else
{
trailCurrent->next = newNode;
newNode->back = trailCurrent;
last = newNode;
}
count++;
}//end else
}//end else
}//end insert
template <class Type>
void doublyLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type> *current; //pointer to traverse the list
nodeType<Type> *trailCurrent; //pointer just before current
bool found;
if (first == NULL)
cout << "Cannot delete from an empty list." << endl;
else if (first->info == deleteItem) //node to be deleted is
//the first node
{
current = first;
first = first->next;
if (first != NULL)
first->back = NULL;
else
last = NULL;
count--;
delete current;
}
else
{
found = false;
current = first;
while (current != NULL && !found) //search the list
if (current->info >= deleteItem)
found = true;
else
current = current->next;
if (current == NULL)
cout << "The item to be deleted is not in "
<< "the list." << endl;
else if (current->info == deleteItem) //check for
//equality
{
trailCurrent = current->back;
trailCurrent->next = current->next;
if (current->next != NULL)
current->next->back = trailCurrent;
if (current == last)
last = trailCurrent;
count--;
delete current;
}
else
cout << "The item to be deleted is not in list."
<< endl;
}//end else
}//end deleteNode
template <class Type>
void doublyLinkedList<Type>::copyList(const doublyLinkedList<Type>& otherList)
{
//cout << "The definition of this function is left as an exercise." << endl;
//cout << "See Programming Execrise 9." << endl;
template <class Type>
doublyLinkedList<Type>::doublyLinkedList(const doublyLinkedList<Type>& otherList)
{
// cout << "The definition of the copy constructor is left as an exercise." << endl;
// cout << "See Programming Execrise 9." << endl;
}
template <class Type>
const doublyLinkedList<Type>& doublyLinkedList<Type>::operator=
(const doublyLinkedList<Type> &)
// cout << "Overloading the assignment operator is left as an exercise." << endl;
// cout << "See Programming Execrise 9." << endl;
}
template <class Type>
doublyLinkedList<Type>::~doublyLinkedList()
{
//cout << "Definition of the destructor is left as an exercise." << endl;
//cout << "See Programming Execrise 9." << endl;
}
Main Function:
//Program to test various operations on a doubly linked list
#include <iostream>
#include "doublyLinkedList.h"
using namespace std;
int main()
{
char choice;
int n = 0;
doublyLinkedList<int> myList;
cout<<"this is a test"<<endl;
do {
cout<<"Main Menu:"<<endl;
cout<<"Choice of operations to perform on Dobule Linked List"<<endl;
cout<<"Create list values : C"<<endl;
cout<<"Initialize List: Z"<<endl;
cout<<"Check List Empty: M"<<endl;
cout<<"Destroy List: E "<<endl;
cout<<"Print List : P"<<endl;
cout<<"Reverse printed list: R"<<endl;
cout<<"Length of List: L"<<endl;
cout <<"Front of List: F"<<endl;
cout<<"Back of List: B"<<endl;
cout<<"Search list: S"<<endl;
cout<<"Insert List: I"<<endl;
cout<<"delete list: D"<<endl;
cout<<"use copy constructor : U" <<endl;
cout <<"quit: Q"<<endl;
cin >> choice;
if ((choice == 'I' )|| (choice =='D')|| (choice == 'S'))
{
cout<<"Enter value to manipulate: "<<endl;
cin >> n;
}
switch ( choice)
{
case 'C':
cout<<"Please enter a list"<<endl;
while(n!= -999){
myList.insert(n);
cin>>n;}
break;
case 'S': if (myList.search(n))
cout<< " List contains: "<<n<<endl;
else
cout<<"List does not contain "<<n<<endl;
break;
case 'I':
myList.insert(n);
cout<<"element was inserted"<<endl;
break;
case 'D':
myList.deleteNode(n);
cout<<"node was deleted"<<endl;
break;
case 'L': cout<<"Length is \n"<<endl;
myList.length();
break;
case 'B':
cout<<"back element is : "<< myList.back();
break;
case 'F' :
cout<<"front element is "<<myList.front();
break;
case 'Z' : myList.initializeList();
cout<<"list initialized"<<endl;
case 'M': if (myList.isEmptyList())
cout<<"is empty"<< endl;
else
cout<<"is not empty"<<endl;
break;
case 'E': myList.destroy();
cout<<"list destroyed"<<endl;
break;
case 'P': myList.print();
break;
case'R': cout<<"reversed"<<endl;
myList.reversePrint();
break;
}
}while(choice!= 'Q');
return 0;
}
I am looking for guidance. I know the answer is really simple and I am just not seeing it. I thought about using the keyword extern but am not sure really how to use it. Like I said in the tags this is homework so I am not looking for a quick fix I am looking to learn from my mistakes.
I really appreciate this site and all the members.
All the code i posted on here was available for free by the book publisher, I have left out my original code except for main.cpp
You need to move your implementation into the header file. Unlike normal functions the compiler needs to be able to see all of the template code at the point of use.
See the answers in this question for more information:
Why can templates only be implemented in the header file?
The problem is that you don't have the template definitions available in your main compilation unit (where they are used).
This means you need to have explicit instantiations for the types it is used with.
Add
template class doublyLinkedList<int>;
to the end of doublyLinkedList.cpp to explicitely instantiate it.
Or include the cpp in the header,
or directly into main.cpp