when I try to implement a Binary tree with a few essential functions, there were no error pop up. However, when I initialize the tree and try to use its functions, there's a compile error showing, and I don't know how to fix it, can you help me. The following is my code and the error that shows:
Edit: I fix the problem by changing the argument of addItem(T& item) to addItem(const T& item). Thank you for your help!
Node.h
#ifndef BINARYTREE_NODE_H
#define BINARYTREE_NODE_H
template <class T>
class Node {
public:
Node<T>* left;
Node<T>* right;
T data;
};
BinaryTree.h
#ifndef BINARYTREE_BINARYTREE_H
#define BINARYTREE_BINARYTREE_H
#include "Node.h"
enum Traversal
{
INORDER,
POSTORDER,
PREORDER
};
template <class T>
class BinaryTree {
private:
Node<T>* root;
int size = 0;
Traversal currentTraversal;
void inOrder(Node<T>* parent,void f(T&));
void preOrder(Node<T>* parent,void f(T&));
void postOrder(Node<T>* parent,void f(T&));
Node<T>* insert(Node<T>* parent, T item);
public:
void setTraversal(Traversal order);
void addItem(const T& item);
BinaryTree();
void print(T& item);
};
#include "BinaryTree.cpp"
#endif //BINARYTREE_BINARYTREE_H
BinaryTree.cpp
#ifndef BINARYTREE_BINARYTREE_CPP
#define BINARYTREE_BINARYTREE_CPP
#include <iostream>
#include "BinaryTree.h"
template <class T>
BinaryTree<T>::BinaryTree() {
root = nullptr;
}
template <class T>
Node<T>* BinaryTree<T>::insert(Node<T> *parent, T item) {
if(parent == nullptr)
{
Node<T>* temp = new Node<T>;
temp->data = item;
return temp;
}
else if(parent->data > item)
{
if (parent->left != nullptr)
insert(parent->left,item);
else{
parent->left = new Node<T>;
parent->left->data = item;
parent->left->left = nullptr;
parent->left->right = nullptr;
}
}
else if (parent->data <= item)
{
if (parent->right != nullptr)
insert(parent->right,item);
else{
parent->right = new Node<T>;
parent->right->data = item;
parent->right->left = nullptr;
parent->right->right = nullptr;
}
}
}
template <class T>
void BinaryTree<T>::addItem(constT &item) {
insert(root,item);
size++;
}
template <class T>
void BinaryTree<T>::inOrder(Node<T> *parent, void f(T&))
{
if (parent != nullptr)
{
inOrder(f, parent->left);
f(parent->data);
inOrder(f,parent->right);
}
}
template <class T>
void BinaryTree<T>::preOrder(Node<T> *parent, void f(T&)) {
if (parent != nullptr)
{
f(parent->data);
preOrder(f,parent->left);
preOrder(f,parent->right);
}
}
template <class T>
void BinaryTree<T>::postOrder(Node<T> *parent, void f(T&)) {
if (parent != nullptr)
{
postOrder(f,parent->left);
postOrder(f,parent->right);
f(parent->data);
}
}
template <class T>
void BinaryTree<T>::print(T& item)
{
std::cout << item <<std::endl;
if(currentTraversal == PREORDER)
preOrder(root,print(item));
if (currentTraversal == POSTORDER)
postOrder(root,print(item));
if(currentTraversal == INORDER)
inOrder(root,print(item));
}
template <class T>
void BinaryTree<T>::setTraversal(Traversal order) {
currentTraversal = order;
}
#endif
main.cpp
#include <iostream>
#include "BinaryTree.h"
int main() {
BinaryTree<int> tree;
tree.addItem(2); // Here's the error showing: "Non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'"
}
You have:
T &item
As the argument to addItem(). It should either be a const reference or a plain value. That is, const T & or T.
For more on why this is the case, see: How come a non-const reference cannot bind to a temporary object?
Related
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
I'm trying to create a individual List with a templated value, but unfortunately I can not link from my List to the ListElements with templates.
In my main I call List<int> list1; to create a instance of the class List.
A List contains multiple ListElements that contain the value, that should be templated.
Compiler throws an error at
ListElement* first;
ListElement* last;
in List.h.
It says C2955 - 'ListElement' : use of class type requires type argument list
List.h
#pragma once
#include <string>
#include "ListElement.h"
template<class T>
class List
{
private:
ListElement* first;
ListElement* last;
public:
List();
~List();
void printList();
void pushBack(T value);
void pushFront(T value);
};
List.cpp
#include <iostream>
#include "List.h"
template<class T>
List<T>::List()
{
first = NULL;
last = NULL;
}
template<class T>
List<T>::~List()
{
}
template<class T>
void List<T>::pushBack(T value)
{
if (last)
{
ListElement* tmp = last;
last = new ListElement(value);
last->setPrev(tmp);
tmp->setNext(last);
}
else
{
first = new ListElement(value);
last = first;
}
}
template<class T>
void List<T>::pushFront(T value)
{
if (first)
{
ListElement* tmp = first;
first = new ListElement(value);
first->setNext(tmp);
tmp->setPrev(first);
}
else
{
last = new ListElement(value);
first = last;
}
}
template<class T>
void List<T>::printList()
{
if (first)
{
ListElement* tmp = first;
while (tmp)
{
std::cout << tmp->getValue() << std::endl;
if (tmp != last)
tmp = tmp->getNext();
else
break;
}
}
else
{
std::cout << "List is empty!" << std::endl;
}
}
template class List<int>;
template class List<std::string>;
ListElement.h
#pragma once
#include <string>
template<class T>
class ListElement
{
private:
ListElement* next;
ListElement* prev;
T value;
public:
ListElement(T val);
~ListElement();
ListElement* getNext() { return next; }
ListElement* getPrev() { return prev; }
void setNext(ListElement* elem) { next = elem; }
void setPrev(ListElement* elem) { prev = elem; }
T getValue() { return value; }
};
ListElement.cpp
#include "ListElement.h"
template<class T>
ListElement<T>::ListElement(T val)
{
value = val;
}
template<class T>
ListElement<T>::~ListElement()
{
}
template class ListElement<int>;
template class ListElement<std::string>;
ListElement is a template, so you want to use a specific instantiation for your pointers:
template<class T>
class List
{
private:
ListElement<T>* first;
ListElement<T>* last;
// note: ^^^
likewise for other occurrences. Only within the template, the template name is usable for the current instantiation, i.e., within List, you can use List as a shortcut for List<T>.
I have a problem with creating base class for DoubleLinkedList.
Right now it's giving me this error
/tmp/cc3lORia.o:(.rodata._ZTV24AbstractDoubleLinkedListIiE[_ZTV24AbstractDoubleLinkedListIiE]+0x10):
undefined reference to
`AbstractDoubleLinkedList::createNewNode(int)' collect2: error:
ld returned 1 exit status
I've tried this and that as you can see by commented lines in code, but none of it works.
So how to define abstract template class with abstract method (factory method by the way) and then redefine it in children classes?
/*
* AbstractDoubleLinkedList.hpp
*
* Created on: Mar 2, 2015
* Author: michael
*/
#ifndef ABSTRACTDOUBLELINKEDLIST_H_
#define ABSTRACTDOUBLELINKEDLIST_H_
#include <vector>
using namespace std;
template <class T> class ListNode {
private:
void init();
public:
ListNode();
ListNode(T value);
ListNode *previous;
ListNode *next;
T value;
};
template <class T> void ListNode<T>::init() {
previous = nullptr;
next = nullptr;
}
template <class T> ListNode<T>::ListNode() {
init();
}
template <class T> ListNode<T>::ListNode(T value) {
init();
this->value = value;
}
template <class T> class AbstractDoubleLinkedList {
private:
void pullOutNode(ListNode<T> *node);
protected:
virtual ListNode<T>* createNewNode(T element);
public:
AbstractDoubleLinkedList();
void push_back(T element);
T front();
T back();
void insertBefore(ListNode<T> *node, ListNode<T> *beforeNode);
void insertAfter(ListNode<T> *node, ListNode<T> *afterNode);
void moveNodeAfter(ListNode<T> *node, ListNode<T> *afterNode);
vector<T> toVector();
ListNode<T> *frontNode;
ListNode<T> *backNode;
};
template <class T> void AbstractDoubleLinkedList<T>::push_back(T element) {
ListNode<T>* node = createNewNode(element);
node->previous = backNode;
if (backNode != nullptr) {
backNode->next = node;
node->previous = backNode;
}
else {
frontNode = node;
}
backNode = node;
}
template <class T> void AbstractDoubleLinkedList<T>::pullOutNode(ListNode<T> *node) {
if (node != frontNode) {
node->previous->next = node->next;
}
else {
frontNode = node->next;
}
if (node != backNode) {
node->next->previous = node->previous;
}
else {
backNode = node->previous;
}
}
template <class T> T AbstractDoubleLinkedList<T>::front() {
return frontNode->value;
}
template <class T> T AbstractDoubleLinkedList<T>::back() {
return backNode->value;
}
template <class T> void AbstractDoubleLinkedList<T>::insertAfter(ListNode<T> *node, ListNode<T> *afterNode) {
node->previous = afterNode;
node->next = afterNode->next;
afterNode->next = node;
if (afterNode == backNode) {
backNode = node;
}
}
template <class T> void AbstractDoubleLinkedList<T>::insertBefore(ListNode<T> *node, ListNode<T> *beforeNode) {
node->next = beforeNode;
beforeNode->previous->next = node;
beforeNode->previous = node;
if (beforeNode == frontNode) {
frontNode = node;
}
}
template <class T> void AbstractDoubleLinkedList<T>::moveNodeAfter(ListNode<T> *node, ListNode<T> *afterNode) {
pullOutNode(node);
node->previous = afterNode;
node->next = afterNode->next;
if (node->next == nullptr) {
backNode = node;
}
afterNode->next = node;
}
template <class T> vector<T> AbstractDoubleLinkedList<T>::toVector() {
ListNode<T>* node = frontNode;
vector<int> listAsVector;
bool shouldHaveAnother = (frontNode != nullptr);
while(shouldHaveAnother) {
listAsVector.push_back(node->value);
if (node->next != nullptr)
node = node->next;
else {
shouldHaveAnother = false;
}
}
return listAsVector;
}
template <class T> AbstractDoubleLinkedList<T>::AbstractDoubleLinkedList() {
frontNode = nullptr;
backNode = nullptr;
}
#endif /* ABSTRACTDOUBLELINKEDLIST_HPP_ */
/*
* DoubleLinkedList.hpp
*
* Created on: Feb 26, 2015
* Author: michael
*/
#ifndef DOUBLELINKEDLIST_HPP_
#define DOUBLELINKEDLIST_HPP_
#include "AbstractDoubleLinkedList.hpp"
template <class T> class DoubleLinkedList : public AbstractDoubleLinkedList<T> {
protected:
ListNode<T>* createNewNode(T element) {
return new ListNode<T>(element);
}
public:
~DoubleLinkedList() {
ListNode<T>* node = this->backNode;
bool shouldHaveAnother = (node != nullptr);
while(shouldHaveAnother) {
ListNode<T>* ptr = node->previous;
delete node;
if (ptr != nullptr)
node = ptr;
else {
shouldHaveAnother = false;
}
}
};
};
//template <class T> ListNode<T> DoubleLinkedList<T>::createNewNode(T element) {
// return new ListNode<T>(element);
//}
//template <class T> DoubleLinkedList<T>::~DoubleLinkedList() {
//
// ListNode<T>* node = this->backNode;
// bool shouldHaveAnother = (node != nullptr);
// while(shouldHaveAnother) {
// ListNode<T>* ptr = node->previous;
// delete node;
// if (ptr != nullptr)
// node = ptr;
// else {
// shouldHaveAnother = false;
// }
// }
//}
#endif /* DOUBLELINKEDLIST_HPP_ */
EDIT1:
So, there is a question "Why do I need my own container class and why not use list or vector?"
I need a data structure with constant time random access and constant time deletion and insertion. BUT I've already tried std::unordered_set and It's not good enough (while technically it meets the requirements) because of allocations and deallocations of memory (when deleting and inserting)
So I figured another way. I want to use a linked list with one "guard" element and the end. When I need to "delete" element from it I would move it after guard. And to check if list is "empty" I would check if the first element is the guard element. But I need a constant-time random access. This can be achieved by map of pointers to every element.
But to achieve maximum performance I need to also minimize cache misses. And I thinks that std::list would be scattered across the memory, because it is the normal behaviour for it. So I figured that the only way to do so - is to allocate vector> and then use this preallocated nodes to new elements.
So am I wrong somewhere? Can I achieve maximum performance more easier?
I have a binary search tree class (BST.h) and a node class (Node.h) of which works fine when I store data types such as integers in it. My problem is trying store class objects in my BST and use an attribute from the object as the key. My program also has a student class which contains studentID and studentName. How would I write an operator overload in my student class so every time my BST preforms operation on nodes, it will overload to the student.getID(), instead of operating on the object itself. I have the rough idea of what the overload function should look like but i don't know where it should go or if its coded correctly anyway.
//My attempt at an operator overload
bool operator< (const Student &s1, const Student &s2)
{
return s1.GetID < s2.GetID;
}
//Node.h
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
Node();
T data;
Node *left;
Node *right;
Node(T);
};
template<class T>
Node<T>::Node()
{
}
template<class T>
Node<T>::Node(T d)
{
data = d;
left = NULL;
right = NULL;
}
#endif //
//BST.h
#ifndef BST_H
#define BST_H
#include <iostream>
#include "Node.h"
#include <string>
using namespace std;
template<class T>
class BST
{
public:
BST();
void Insert(T);
Node<T> *Search(T);
void preOrder();
void inOrder();
void postOrder();
~BST();
private:
Node<T> *root;
void Insert(T , Node<T> *aNode);
Node<T> *Search(T, Node<T> *aNode);
void preOrder(Node<T> *aNode);
void inOrder(Node<T> *aNode);
void postOrder(Node<T> *aNode);
};
template<class T>
BST<T>::BST()
{
root = NULL;
}
template<class T>
void BST<T>::Insert(T data, Node<T> *aNode)
{
if (data < aNode->data)
{
if (aNode->left != NULL)
{
Insert(data, aNode->left);
}
else
{
aNode->left = new Node<T>(data);
aNode->left->left = NULL;
aNode->left->right = NULL;
}
}
else
{
if (data >= aNode->data)
{
if (aNode->right != NULL)
{
Insert(data, aNode->right);
}
else
{
aNode->right = new Node<T>(data);
aNode->right->left = NULL;
aNode->right->right = NULL;
}
}
}
}
template<class T>
void BST<T>::Insert(T data)
{
if (root != NULL)
{
Insert(data, root);
}
else
{
root = new Node<T>(data);
root->left = NULL;
root->right = NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data, Node<T> *aNode)
{
if (aNode != NULL)
{
if (data == aNode->data)
{
return aNode;
}
if (data < aNode->data)
{
return Search(data, aNode->left);
}
else
{
return Search(data, aNode->right);
}
}
else
{
return NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data)
{
return Search(data, root);
}
template<class T>
void BST<T>::preOrder()
{
preOrder(root);
}
template<class T>
void BST<T>::preOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
cout << aNode->data << " ";
preOrder(aNode->left);
preOrder(aNode->right);
}
}
template<class T>
void BST<T>::inOrder()
{
inOrder(root);
}
template<class T>
void BST<T>::inOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
inOrder(aNode->left);
cout << aNode->data << " ";
inOrder(aNode->right);
}
}
template<class T>
void BST<T>::postOrder()
{
postOrder(root);
}
template<class T>
void BST<T>::postOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
postOrder(aNode->left);
postOrder(aNode->right);
cout << aNode->data << " ";
}
}
template<class T>
BST<T>::~BST()
{
}
#endif // !BST_H
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student();
Student(string, int);
~Student();
int Student::GetID();
private:
string name;
int ID;
};
inline int Student::GetID()
{
return ID;
}
You seem to be asking about operator< taking Students , however Student is not a class template, so the title of your post is baffling.
As someone else pointed out, your operator< is almost correct, except you have to actually call GetID() instead of comparing pointers to member functions.
This won't work yet until you fix GetID however. Instead of int Student::GetID(); it should be:
int GetID() const;
The const means that it can be called on objects passed by const reference, as you have in your operator< implementation. And you don't repeat the Student:: when declaring functions inside the class. (You use it when defining class members outside of the class definition).
Declare it as a friend function within your Student class, next to the rest of your member functions
friend bool operator < (Student& s1, Student& s2);
Your implementation is correct, it should go outside your Student class within the same header file.
This question already has answers here:
Why do I get "unresolved external symbol" errors when using templates? [duplicate]
(3 answers)
Undefined reference to template members
(1 answer)
Closed 10 years ago.
I always get
undefined reference to `Graph::InsertVertex(std::string)'
if I compile my project! Any hints why he cant resolve this reference?
(all Files are in the netbeans project folder)
// main.cpp
#include <cstdlib>
#include <string>
#include "Graph.h"
using namespace std;
int main(int argc, char** argv)
{
Graph<string> *graph = new Graph<string>(); // <--- ERROR
graph->InsertVertex("A");
return 0;
}
// Node.h
#include <iostream>
#include "Graph.h"
template<class T>
class Node
{
friend class Graph;
public:
Node(T val)
{
this->data = val;
this->vertList = NULL;
this->next = NULL;
}
Node(const Node& orig);
virtual ~Node();
private:
T data;
Node<T> *vertList;
Node<T> *next;
int status;
};
// Graph.h
#include <iostream>
#include "Node.h"
template <class T>
class Graph
{
public:
Graph()
{
head = NULL;
}
void InsertVertex(T val);
void InsertEdge(T v_val, T e_val);
void PrintVertices();
void PrintEdges(T v_val);
void DeleteEdge(T v_val, T e_val);
void DeleteVertex(T val);
void bfs();
private:
Node<T> *head;
};
// Graph.cpp
#include "Graph.h"
template <class T>
void Graph<T>::InsertVertex(T val)
{
Node<T> *temp = new Node<T>(val);
if(head == NULL) head = temp;
else
{
Node<T> node = head;
while(node->vertList != NULL)
node = node->vertList;
node->vertList = temp;
}
}
template <class T>
void Graph<T>::InsertEdge(T v_val, T e_val)
{
if (head != NULL)
{
Node<T> *k = head;
Node<T> *t = head;
Node<T> *temp = new Node<T> (e_val);
while (t != NULL)
{
if (t->data == v_val)
{
Node<T> *s = t;
while (s->next != NULL)
s = s->next;
s->next = temp;
while (k != NULL)
{
if(k->data == e_val) break;
k = k->vertList;
}
temp->vertList = k;
return;
}
t = t->vertList;
} // end while loop
}
else std::cout << "Add first vertices to the graph" << std::endl;
}
template <class T>
void Graph<T>::PrintEdges(T v_val)
{
Node<T>* t = head;
while (t != NULL)
{
if (t->data == v_val)
{
while (t->next != NULL)
{
std::cout << t->next->vertList->data << " ";
t = t->next;
}
}
t = t->vertList;
}
}
template <class T>
void Graph<T>::PrintVertices()
{
Node<T>* t = head;
while (t != NULL)
{
std::cout << t->data << " ";
t = t->vertList;
}
}
Typically you want your template methods in the header, so they are compiled when needed. In case you really want to hide it in the implementation file, you have to explicitly instantiate the template in Graph.cpp like
template class Graph<string>;
Since you have to do that for every type T you intend to use with Graph<T>, the point of the template class is somewhat defeated and you better put everything into the header
You need to define member functions in a header file, because when instantiating a template, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument.
In your example:
template <class T>
class Graph {
public:
void InsertVertex(T val) {
Node<T> *temp = new Node<T>(val);
if(head == NULL)
head = temp;
// ...
}
// ...
private:
Node<T> *head;
};