I am trying to learn data structures and I started with single linked list. I am first trying to just memorize and understand the code that Walter Savitch provided in Ch.13 of Absolute C++. I am having some trouble using the interface that the author designed for a single linked list. Specifically, I understand the code but I do not understand how to use the interface to create a single linked list in terms of the syntax needed.
Here is the interface:
#ifndef LinkedList_hpp
#define LinkedList_hpp
namespace LinkedList {
template<class T>
class Node {
private:
T data;
Node<T> *link;
public:
Node(const T& theData, Node<T>* theLink) : data(theData), link(theLink) {}
Node<T>* getLink() {return link;}
const T getData() const {return data;}
void setData(const T& theData) {data = theData;}
void setLink(Node<T>* pointer) {link = pointer;}
};
template<class T>
void headInsert(Node<T>*& head, const T& theData) {
head = new Node<T>(theData, head);
}
template<class T>
void insert(Node<T>* next, const T& theData) {
next->setLink(new Node<T>(theData, next->getLink( )));
}
template<class T>
void deleteNode(Node<T>* before) {
Node<T>* discard;
discard = before->getLink();
before->setLink(discard->getLink( ));
delete discard;
}
template<class T>
void deleteFirstNode(Node<T>*& head) {
Node<T>* discard;
discard = head;
head = head->getLink();
delete discard;
}
template<class T>
Node<T>* search(Node<T>* head, const T& target) {
Node<T>* here = head;
if(here == nullptr) {
return nullptr;
}
else {
while(here->getData() != target && here->getLink() != nullptr)
here = here->getLink();
if(here->getData() == target)
return here;
else
return nullptr;
}
}
}
#endif /* LinkedList_hpp */
Now I am trying to just use the interface to create a single linked list. But I am having some trouble. Here is how far I have gone.
#include <iostream>
#include "LinkedList.hpp"
using namespace LinkedList;
int main(int argc, const char * argv[]) {
Node<int> test(2,nullptr);
return 0;
}
Can anyone help me just show me what I need to write into the int main() body to create a single linked list and perhaps print its contents? Just for ease of simplicity I want to try to make a single linked list look like this:
Here's how that interface could be accessed:
Node<int> node(20,nullptr);
Node<int> *head = &node;
insert(head, 30);
prnt(head);
std::cout << "Searching for 10..." << search(head, 10) << std::endl;
headInsert(head, 10);
std::cout << "Searching for 10..." << search(head, 10) << std::endl;
prnt(head);
deleteFirstNode(head);
prnt(head);
deleteNode(head);
prnt(head);
Included is prnt method, which traverses the current list from the head until it finds a nullptr, printing the data at each node and helps demonstrate what each method does. The method is as follows:
template<class T>
void prnt(Node<T>* head) {
for (; head->getLink(); head=head->getLink()){
std::cout << head->getData() << " -> ";
}
std::cout << head->getData() << std::endl;
}
Related
Locked for 3540 days. Comments on this question have been disabled, but it is still accepting new answers and other interactions. Learn more.
I am running the following program. In this program I have to implement a doubly linked list. And I am still to complete this program. Howvever, look below at the program I have so far. I am getting an error "Unknown type name 'Node'" in the function:
template<typename T>
Node* LinkedList<T>::Find(const T& val) const {
Node *itr = nullptr;
Node *ptr = head->next;
while (ptr != tail) {
if (ptr->data == val) {
*itr = *ptr;
break;
}
ptr = ptr->next;
}
return *itr;
}
I cannot understand why I am getting that error, and what I can do to fix it. What would be the solution to fix this error?
#include <iostream>
#include <vector>
using namespace std;
template<typename T>
class LinkedList{
public:
struct Node {
T data;
Node* prev;
Node* next;
};
void PrintForward();
void PrintReverse();
void PrintForwardRecursive(const Node*);
void PrintReverseRecursive(const Node*);
int NodeCount() const;
void FindAll(vector<Node*>&, const T&);
Node* Find(const T&) const;
Node* GetNode(int& ) const;
Node* Head() const;
Node* Tail() const;
void AddHead(const T&);
void AddTail(const T&);
void AddNodesHead(const T&, int);
void AddNodesTail(const T&, int);
void InsertAfter(Node*, const T&);
void InsertBefore(Node*, const T&);
void InsertAt(const T&, int);
bool RemoveHead();
bool RemoveTail();
int Remove(const T&);
bool RemoveAt(int);
void clear();
T& operator[](int);
bool operator==(const LinkedList<T>&);
LinkedList<T>& operator=(const LinkedList<T>&);
LinkedList();
LinkedList(const LinkedList<T>&);
~LinkedList();
private:
int n;
Node* head;
Node* tail;
};
template<typename T>
void LinkedList<T>::PrintForward() {
PrintForwardRecursive(head->next);
}
template<typename T>
void LinkedList<T>::PrintReverse() {
PrintReverseRecursive(tail->prev);
}
template<typename T>
void LinkedList<T>::PrintForwardRecursive(const Node* node) {
cout << node->data << " ";
if (node->next != tail)
PrintForwardRecursive(node->next);
}
template<typename T>
void LinkedList<T>::PrintReverseRecursive(const Node* node) {
cout << node->data << " ";
if (node->next != prev)
PrintForwardRecursive(node->prev);
}
template<typename T>
int LinkedList<T>::NodeCount() const {
int num = 1;
Node *ptr = head;
while (ptr != tail) {
ptr = ptr->next;
num++;
}
return num;
}
template<typename T>
void LinkedList<T>::FindAll(vector<Node*>&matches, const T& val) {
Node *ptr = head->next;
while (ptr != tail) {
if (ptr->data == val)
matches.push_back(*ptr);
ptr = ptr->next;
}
}
template<typename T>
Node* LinkedList<T>::Find(const T& val) {
Node *itr = nullptr;
Node *ptr = head->next;
while (ptr != tail) {
if (ptr->data == val) {
*itr = *ptr;
break;
}
ptr = ptr->next;
}
return *itr;
}
template<typename T>
LinkedList<T>::LinkedList() {
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
n = 0;
}
template<typename T>
LinkedList<T>::~LinkedList() {
bool empty = false;
while (!empty) {
empty = RemoveHead();
}
delete head;
delete tail;
}
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
Locked for 3540 days. Comments on this answer have been disabled, but it is still accepting other interactions. Learn more.
The type Node is a member of LinkedList<T>. That means when you define the function, you need to use
template<typename T>
typename LinkedList<T>::Node* LinkedList<T>::Find(const T& val) const
So that the compiler knows that the Node you are using is the Node from LinkedList. The typename is required to let the compiler know that LinkedList<T>::Node is a member type, and not a member object.
Code for Reversing Linked List with Recursion, using STL
#include<iostream>
#include<conio.h>
#include<list>
using namespace std;
template<typename T>
class node
{
public:
T data;
node<T> *next;
node(){ next = NULL; }
node(const T& item, node<T> *nextnode = NULL)
{
data = item;
next = nextnode;
}
};
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
template<typename T>
void Display( list<T>& alist );
};
int main()
{
Reverse_list <int> rl;
list<int> intlist;
int size, no;
cout << "Size of List ?? ";
cin >> size;
for (int i = 1; i <= size; i++)
{
cout << "Enter the " << i <<" "<< "element";
cin >> no;
intlist.push_front(no);
}
rl.Display(intlist);
rl.Reverse();
rl.Display(intlist);
_getch();
return 0;
}
template<typename T>
void Reverse_list<T>::Display(list<T>& alist)
{
list<int>::iterator iter = alist.begin();
while (iter != alist.end())
{
cout << *iter << " ";
iter++;
}
}
template<typename T>
void Reverse_list<T>::reverse(node<T> *front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<int> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{
reverse(head);
}
The above code generates 2 errors.
Error 1) No instance of function template matches the argument list. ( No error number.)
If I remove line 1 ( mentioned in a code ) then above error is no more. ( Why? )
Error 2) C2783: 'void Reverse_list::Reverse1(void)' : could not deduce template argument for 'T'
How to solve above errors.
In above program , I wanted to pass " head" node ( which is private ) as
argument to Reverse function. But we can not access private member outside of the class. So I passed indirectly. Is this a correct way of passing ?? Or there is some other way of accessing private data ??
I'm not sure to understand your intentions but...
You're trying to declare a method (reverse()) inside another method (Reverse()) ? Uhmmm....
We return to this later.
Imagine that the following instruction is correct instruction of Reverse_list<T>::Reverse()
node<T> *back = front->next;
Why you declare back as a pointer to a generic Node<T> when you assign front->next (so a specific Node<int>) to it?
If you define back as a node<int> pointer, the method Reverse() has no longer reason to be a template (dependant from T) method. And you can avoid both errors.
With your actual code, when you call
rl.Reverse();
you call a template method but the compiler doesn't know how to determine the type T. You could explicit it in this way
rl.Reverse<int>();
but, as written before, I thik it's better if you remove the whole template part.
Or, alternatively, you can transform the whole class in a template class; where head is a pointer to a generic Node<T>, not a specifica Node<int>.
Something like (if I understand correctly your intentions)
template <typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse (node<T> * front);
public:
Reverse_list() : head(NULL)
{ }
void Reverse();
void Display(list<T>& alist);
};
template<typename T>
void Reverse_list<T>::reverse (node<T> * front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<T> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{ reverse(head); }
In this case, in main(), rl should be declared as
Reverse_list<int> rl;
fixing T as int, and the call to Reverse() should be
rl.Reverse();
--- EDIT 2016.05.10 ---
With the "template Reverse_list" solution, you should correct three points (at last).
1) in Reverse_list class declaration, you have commented the template<typename T> row before void Reverse(); good; you should delete (comment) the same line (for the same reason) before void Display( list<T>& alist );; so the class become
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
//template<typename T>
void Display( list<T>& alist );
};
2) Display() now is a method of a templated class; so the line
list<int>::iterator iter = alist.begin();
become
list<T>::iterator iter = alist.begin();
3) reverse() now is a method of a templated class; so the line
node<int> *back = front->next;
become
node<T> *back = front->next;
I'm new to working with class templates and am simply trying to define a temporary node 'temp' in a class associated with the Linked List, which sets the string that the node stores to some temporary string that is created in the function TowerHanoi::set_Discs(size_t disc) via user input. When I call the function temp->set_data(tmp_str) i get a segmentation fault. I tried calling temp->set_data("hello"); on its own and i still get the error.
I'm not sure what's going on here and i've tried researching into it but to no avail. I'm probably missing something obvious, but i'm just quite lost now. Let me know if you need more code. Thanks.
TowerHanoi.cpp:
#include "TowerHanoi.h"
#include <iostream>
#include <cstdlib>
using namespace std;
using oreilly_A2::node;
namespace oreilly_A2 {
TowerHanoi::TowerHanoi() {
for (int i=0;i<2;i++) {
rod[i] = LStack<node<std::string> >();
}
}
TowerHanoi::TowerHanoi(size_t numDiscs) {
for (int i=0; i < 2; i++) {
rod[i] = LStack<node<string> >();
}
discs = numDiscs;
}
void TowerHanoi::set_Discs(size_t disc) {
node<string>* temp=NULL;
while (disc != 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
temp->set_data(tmp_str);
rod[0].push(temp);
}
void TowerHanoi::print_Game() {
for (size_t s=1; s<discs; s++) {
cout << " ";
for (size_t o=1; o<discs-s;o++) {
cout << " ";
}
//cout << tmp_node->data() << endl;
cout << "x" << endl;
}
}
}
node.h file:
#ifndef NODE_CAMERON_H
#define NODE_CAMERON_H
#include <string>
namespace oreilly_A2 {
template <typename Item>
class node {
public:
node(); //constructor for node
node(const Item val, node* newNext); //constructor with parameters
~node(); //destructor
void set_data(Item new_data); //set the word that this node contains
void set_link(node* new_link); //set the 'next' node
void set_previous(node* new_prev);
Item data() const; //return this node's word
const node* link() const; //return next
const node* back() const;
node* link(); //return next
node* back();
private:
node* next; //the next node
node* previous;
Item word; //the word this node contains
};
}
#include "Node.template"
#endif
node.template file:
namespace oreilly_A2 {
template <typename Item>
node<Item>::node() {
next=NULL;
previous=NULL;
}
//Node.template
template <typename Item>
node<Item>::node(const Item val, node* newNext=NULL) {
word = val;
next = newNext;
}
template <typename Item>
node<Item>::~node() {
delete next;
delete previous;
delete word;
}
template <typename Item>
void node<Item>::set_data(Item new_data){
word = new_data;
}
template <typename Item>
void node<Item>::set_link(node* new_link){
next = new_link;
}
template <typename Item>
void node<Item>::set_previous(node* new_back) {
previous = new_back;
}
template <typename Item>
Item node<Item>::data() const { //return the word
return word;
}
template <typename Item>
const node<Item>* node<Item>::link() const { //return next node (const function)
return next;
}
template <typename Item>
const node<Item>* node<Item>::back() const { //return previous node (const)
return previous;
}
template <typename Item>
node<Item>* node<Item>::link() {
return next; //return next node (non-const)
}
template <typename Item>
node<Item>* node<Item>::back() { //return previous node (const)
return previous;
}
}
Unless I have missed something the temp variable is NULL at the time of calling set_data. As any regular object you need to first initialized it.
node<string>* temp=new node<string>();
And then freeing it when appropriate to avoid memory leaks.
This is not the case with temp_str because the later is not a pointer, it's a value so it gets initialized automatically (and also freed automatically when it gets out of scope).
You have initialized temp as NULL. So when you are trying to do temp->set_data(tmp_str); you are actually trying to access NULL pointers.
All you need to do is initialize temp. I have correct the code below
void TowerHanoi::set_Discs(size_t disc) {
node<string>* temp=new node<string>();
while (disc != 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
temp->set_data(tmp_str);
rod[0].push(temp);
}
To avoid memory leak you need to delete all the memory allocated after you are done.
Here is a cut-down version of a template List code (adapted from http://www.daniweb.com/software-development/cpp/threads/237391/c-template-linked-list-help)
List complains (compile error) that "Node is not a type". Why is this, and what is the fix?
I tried replacing the "class Node" with a "struct Node" (and related changes), and the struct version worked fine. So the main question seems to be: how does a template-class access another template-class?
#include <iostream>
using namespace std;
template <typename T>
class Node
{
public:
Node(){}
Node(T theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template <typename T>
class List {
public:
List() {
first = NULL;
last = NULL;
count = 0;
}
void insertFirst(const T& newData) {
first = new Node(newData, first);
++count;
}
void printList() {
Node<T> *tempt;
tempt = first;
while(tempt != NULL){
cout << tempt->getData() << " ";
tempt = tempt->getLink();
}
}
~List() { }
private:
Node<T> *first;
Node<T> *last;
int count;
};
int main() {
List<int> myIntList;
cout << "Inserting 1 in the list...\n";
myIntList.insertFirst(1);
myIntList.printList();
cout << endl;
List<double> myDoubleList;
cout << "Inserting 1.5 in the list...\n";
myDoubleList.insertFirst(1.5);
myDoubleList.printList();
cout << endl;
}
You are using
new Node(newData, first);
within the List template. At that point, Node does not refer to a type, but to a template. But of course to create an instance of a type with new, you need a type there.
The most probable thing you want to do is to make it a type by instantiating the template, i.e.
new Node<T>(newData, first);
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;
};