c++ sort function of List - c++

My sort function looks like this:
template <typename Compare, typename T>
void List<T>::sort(const Compare& comparer){
...
}
But I received next error:
template definition of non-template
void List<T>::sort(const Compare&)'
invalid use of undefined typeclass
List'
What does it mean?
This is the complete code of the list:
template <typename T> class Node;
template <typename T> class Iterator;
template <typename T>
class List{
private:
Node<T> * first;
Node<T> * last;
int size;
friend class Predicate ;
friend class Compare;
public:
typedef Iterator<T> iterator;
List(){
first = NULL;
last = NULL;
size = 0;
}
List(const List<T> & l);
void pushBack(T element);
void insert( const T& element, iterator i);
iterator remove(iterator i);
iterator find(const Predicate& predicate);
void sort(const Compare& comparer);
int getSize() const;
iterator begin();
iterator end();
~List();
};
template <class T>
List<T>::List(const List & l) {
first = 0;
last = 0;
size = 0;
for (Node<T> * current = l.first; current != 0; current = current -> next){
pushBack(current -> data);
}
}
template <typename T>
void List<T>::pushBack(T element){
Node<T>* newnode = new Node<T>(element);
if (newnode->prev == NULL) {
first = newnode;
last = newnode;
}else{
newnode->prev = last;
last->next = newnode;
last = newnode;
}
}
template <typename T>
void List<T>::insert( const T& element, iterator i){
if (i.position == NULL){
pushBack(element);
++size;
return;
}
Node<T>* after = i.position;
Node<T>* before = after->prev;
Node<T>* newnode = new Node<T>(element);
newnode->prev = before;
newnode->next = after;
after->prev = newnode;
if (before == NULL) {
first = newnode;
}
else{
before->next = newnode;
}
++size;
}
template <typename T>
typename List<T>::iterator List<T>::remove(iterator iter){
if(iter.position != NULL){
Node<T>* remove = iter.position;
Node<T>* before = remove->prev;
Node<T>* after = remove->next;
if (remove == first){
first = after;
} else{
before->next = after;
}
if (remove == last){
last = before;
}else{
after->prev = before;
}
iter.position = after;
--size;
delete remove;
return iter;
}else{
throw ElementNotFound();
}
}
template <typename T>
typename List<T>::iterator List<T>::begin(){
//iterator iter;
//iter.position = first;
//iter.last = last;
return iterator(first);
}
template <typename T>
typename List<T>::iterator List<T>::end(){
return iterator (last);
}
template <typename Predicate, typename T>
List<T>::iterator List<T>::find(const Predicate& predicate){
iterator iter;
for( iter = begin(); iter != end(); iter = next()){
if( predicate(iter.getElement())){
return iter;
}
}
return end();
}
template <typename Compare, typename T>
void List<T>::sort(const Compare& comparer){
Iterator<T> iter;
for( iter = begin(); iter != end(); iter = iter.next() ){
if( comparer( iter.getElement() , (iter+1).getElement()) != true){
}
}
}
template <typename T>
int List<T>::getSize() const{
return size;
}
template <class T>
List <T>::~List() {
Node <T> * firstNode = first;
while (firstNode != 0) {
Node <T> * nextNode = firstNode->next;
delete firstNode;
firstNode = nextNode;
}
}
template <typename T> class Node {
private:
T data;
Node* next;
Node* prev;
friend class List<T>;
friend class Iterator<T>;
public:
Node(T element){
data = element;
prev = NULL;
next = NULL;
}
~Node(){}
};
template <typename T> class Iterator{
private:
Node<T>* position;
Node<T>* last;
friend class List<T>;
public:
Iterator(){
position = NULL;
last = NULL;
}
Iterator(Node<T> * source): position(source) { }
T& getElement()const;
bool operator==(Iterator b) const;
bool operator!=(Iterator b) const;
T & operator*();
Iterator & operator++();
Iterator & operator++(int);
~Iterator(){}
};
template <class T>
T& Iterator<T>::getElement() const{
if(position != NULL){
return position->data;
}
else{
throw ElementNotFound();
}
}
template <typename T>
bool Iterator<T>::operator==(Iterator b) const{
return position == b.position;
}
template <typename T>
bool Iterator<T>::operator!=(Iterator b) const{
return position != b.position;
}
template <typename T>
T & Iterator<T>::operator*() {
return position->data;
}
template <class T>
Iterator<T> & Iterator<T>::operator++() {
position = position->next;
return *this;
}
template <class T>
Iterator<T> & Iterator<T>::operator++(int){
position = position->next;
return *this;
}
#endif /* LISTGENERIC_H_ */

Either you declare sort as a template function with one template argument (Compare) inside the class. Then your definition has to look as follows:
template <typename T>
template <typename Compare>
void List<T>::sort(const Compare& comparer) {
…
}
And you also need to remove the now redundant friend class Compare declaration from your List class.
Or you keep Compare and sort as-is. In this case, simply don’t have sort as a template, and omit the Compare template argument:
template <typename T>
void List<T>::sort(const Compare& comparer) {
…
}
Of course this only works if you have defined (not just declared!) the class Compare before this function.
But this second solution would be highly unorthodox and pretty useless since the compare argument doesn’t make much sense: there is only one Compare class and the user cannot change it. Normally, this should be a template argument (first solution).

Related

Segmentation fault (core dumped) eror in c++ (iterator overloading)

I'm tring to implement the doubly linked list and also iterators and i only want to add a single node and test my print function which have iterators in it.but somehow ( i don't know really ) i'm facing the Segmentation fault (core dumped) eror and it's my first time facing this eror and i read about it and i understand the eror but i can't find where i do the mistake!
doublylinkedlist.h
#ifndef DoublyLinkedList_H
#define DoublyLinkedList_H
#include <iostream>
#ifndef DoublyLinkedList_H
#define DoublyLinkedList_H
#include <iostream>
template <class T>
class DoublyLinkedList;
// List Node class
template <class T>
class DoublyLinkedListNode
{
friend class DoublyLinkedList<T>;
friend class DoublyLinkedList<T>::Iterator_Base;
friend class DoublyLinkedList<T>::Iterator;
friend class DoublyLinkedList<T>::Reverse_Iterator;
private:
T data; // data
DoublyLinkedListNode<T> *llink; // left link
DoublyLinkedListNode<T> *rlink; // right link
};
// List class
template <class T>
class DoublyLinkedList
{
public:
typedef DoublyLinkedListNode<T> NodeType;
// iterator
class Iterator_Base
{
public:
Iterator_Base(NodeType *startNode = 0) { current = startNode; }
~Iterator_Base() {}
Iterator_Base(const Iterator_Base &source) { current = source.current; }
// dereferencing operators
T &operator*() const { return current->data; }
T *operator->() const { return &current->data; }
// get the node pointer directly
NodeType *GetNodePointer() { return current; }
// equality testing
bool operator!=(const Iterator_Base it) const
{
return current != it.current;
}
bool operator==(const Iterator_Base it) const
{
return current == it.current;
}
protected:
NodeType *current;
};
class Iterator : public Iterator_Base
{
public:
Iterator(NodeType *startNode = 0) : Iterator_Base(startNode) {}
Iterator &operator++(); // ToDo
Iterator operator++(int); // ToDo
Iterator &operator--(); // ToDo
Iterator operator--(int); // ToDo
};
class Reverse_Iterator : public Iterator_Base
{
public:
Reverse_Iterator(NodeType *startNode = 0) : Iterator_Base(startNode) {}
Reverse_Iterator &operator++(); // ToDo
Reverse_Iterator operator++(int); // ToDo
Reverse_Iterator &operator--(); // ToDo
Reverse_Iterator operator--(int); // ToDo
};
// Default constructor - ToDo
DoublyLinkedList();
// Copy constructor - ToDo
DoublyLinkedList(const DoublyLinkedList &source);
// Destructor - ToDo
~DoublyLinkedList();
// Assignment operator - ToDo
DoublyLinkedList &operator=(const DoublyLinkedList &source);
// Get leftmost node iterator
Iterator Begin() const
{
Iterator it(first);
return ++it;
};
// Get end iterator
Iterator End() const
{
Iterator it(first);
return it;
}
// Get rightmost iterator
Reverse_Iterator rBegin() const
{
Reverse_Iterator it(first);
return ++it;
};
// Get end iterator
Reverse_Iterator rEnd() const
{
Reverse_Iterator it(first);
return it;
}
// Insert a new node to the list as the first node
// Return the pointer of new node - ToDo
Iterator InsertFirst(const T &data);
// Insert a new node to the list as the last node
// Return the pointer of new node - ToDo
Iterator InsertLast(const T &data);
// Insert a new node to the list after pos
// Return the pointer of new node - ToDo
Iterator InsertNext(Iterator pos, const T &data);
// Insert a new node to the list before pos
// Return the pointer of new node - ToDo
Iterator InsertPrev(Iterator pos, const T &data);
// Total number of nodes in the list - ToDo
int Size() const;
// Delete node at pos in the list - ToDo
bool DeleteNode(Iterator pos);
// Delete first node - ToDo
bool DeleteFirst();
// Delete last node - ToDo
bool DeleteLast();
// Print list
void Print(bool reverse = false);
private:
// first pointer of the list
NodeType *first;
};
#ifndef DoublyLinkedList_TXX
#include "doublylinkedlist.txx"
#endif
#endif
doublylinkedlist.txx
#include "doublylinkedlist.h"
#include <iostream>
#include <math.h>
template <class T>
typename DoublyLinkedList<T>::Iterator &
DoublyLinkedList<T>::Iterator::operator++()
{
this->current = this->current->rlink;
return *this;
}
template <class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::Iterator::operator++(int)
{
DoublyLinkedList<T>::Iterator temp = *this;
++(*this);
return temp;
}
template <class T>
typename DoublyLinkedList<T>::Iterator &
DoublyLinkedList<T>::Iterator::operator--()
{
this->current = this->current->llink;
return *this;
}
template <class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::Iterator::operator--(int)
{
DoublyLinkedList<T>::Iterator temp = *this;
--(*this);
return temp;
}
/*
* Reverse Iterator
*/
template <class T>
typename DoublyLinkedList<T>::Reverse_Iterator &
DoublyLinkedList<T>::Reverse_Iterator::operator++()
{
this->current = this->current->llink;
return *this;
}
template <class T>
typename DoublyLinkedList<T>::Reverse_Iterator
DoublyLinkedList<T>::Reverse_Iterator::operator++(int)
{
DoublyLinkedList<T>::Reverse_Iterator temp = *this;
++(*this);
return temp;
}
template <class T>
typename DoublyLinkedList<T>::Reverse_Iterator &
DoublyLinkedList<T>::Reverse_Iterator::operator--()
{
this->current = this->current->rlink;
return *this;
}
template <class T>
typename DoublyLinkedList<T>::Reverse_Iterator
DoublyLinkedList<T>::Reverse_Iterator::operator--(int)
{
DoublyLinkedList<T>::Reverse_Iterator temp = *this;
--(*this);
return temp;
}
/*
* Doubly linked list
*/
// Default constructor
template <class T>
DoublyLinkedList<T>::DoublyLinkedList()
{
this->first = NULL;
}
// Copy constructor
template <class T>
DoublyLinkedList<T>::DoublyLinkedList(const DoublyLinkedList &source)
{
// ToDo
}
// Destructor
template <class T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
// ToDo
}
/*
// Assignment operator
template <class T>
DoublyLinkedList<T> &
DoublyLinkedList<T>::operator=(const DoublyLinkedList<T> &source)
{
// ToDo
}
// Total number of nodes in the list
template <class T>
int DoublyLinkedList<T>::Size() const
{
// ToDo
}
*/
// Insert a new node to the list as the first node
// Return the pointer of new node
template <class T>
typename DoublyLinkedList<T>::Iterator
// typename Iterator
DoublyLinkedList<T>::InsertFirst(const T &data)
{
if (first != NULL)
{
printf("worked");
}
else
{
DoublyLinkedListNode<T> *newNode = new DoublyLinkedListNode<T>();
newNode->data = data;
newNode->rlink = NULL;
newNode->llink = NULL;
this->first = newNode;
}
}
/*
// Insert a new node to the list as the last node
// Return the pointer of new node
template <class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::InsertLast(const T &data)
{
// ToDo
}
/*
// Insert a new node to the list after pos
// Return the pointer of new node
template <class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::InsertNext(DoublyLinkedList<T>::Iterator pos, const T &data)
{
// ToDo
}
// Insert a new node to the list before pos
// Return the pointer of new node
template <class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::InsertPrev(Iterator, const T &data)
{
// ToDo
}
// Delete node at pos in the list
template <class T>
bool DoublyLinkedList<T>::DeleteNode(Iterator pos)
{
// ToDo
}
// Delete first node
template <class T>
bool DoublyLinkedList<T>::DeleteFirst()
{
// ToDo
}
// Delete last node
template <class T>
bool DoublyLinkedList<T>::DeleteLast()
{
// ToDo
}
*/
template <class T>
void DoublyLinkedList<T>::Print(bool reverse)
{
if (reverse)
{
for (Reverse_Iterator rit = rBegin(); rit != rEnd(); rit++)
{
std::cout << *rit << ", ";
}
}
else
{
for (Iterator it = Begin(); it != End(); it++)
{
std::cout << *it << ", ";
}
}
std::cout << std::endl;
}
i'm only using this in my main.cpp to test InsertFirst() and Print()
DoublyLinkedList<int> list;
list.InsertFirst(10);
list.Print();
PS
the goal of this code is to test the iterators for my print fucntion so thats why i comment other fucntions.

Restruct list iterator after erase

I've created a custom Node, Iterator and List.
I would like to do:
List<int> list;
// push_back objects here...
List<int>::Iterator it = list.begin();
list.erase(it);
++it;
list.erase(it); // error here
So I need to reconstruct the iterator after erasing an element. How do I do that?
Node.h
#pragma once
namespace Util
{
template<typename T>
class Node
{
public:
template<typename T> friend class Iterator;
template<typename T> friend class List;
private:
Node();
Node(T);
~Node();
/* unlink(): takes out this node
and links next and prev to each other
prev <- this -> next
prev <- -> next
this <- this -> this
*/
void unlink();
private:
T value;
Node<T>* next;
Node<T>* prev;
};
template<typename T>
Node<T>::Node() : next(this), prev(this)
{
// ...
}
template<typename T>
Node<T>::Node(T t) : value(t), next(this), prev(this)
{
// ...
}
template<typename T>
Node<T>::~Node()
{
unlink();
}
template<typename T>
void Node<T>::unlink()
{
next->prev = prev;
prev->next = next;
next = this;
prev = this;
}
}
Iterator.h
#pragma once
#include "Node.h"
namespace Util
{
template<typename T>
class Iterator
{
public:
template<typename T> friend class List;
Iterator& operator++();
T& operator*() const;
bool operator==(const Iterator& rhs) const;
bool operator!=(const Iterator& rhs) const;
private:
Iterator(Node<T>* n);
Node<T>* node;
};
template<typename T>
Iterator<T>::Iterator(Node<T>* n) : node(n)
{
// ...
}
template<typename T>
Iterator<T>& Iterator<T>::operator++()
{
node = node->next;
return *this;
}
template<typename T>
T& Iterator<T>::operator*() const
{
return node->value;
}
template<typename T>
bool Iterator<T>::operator==(const Iterator& rhs) const
{
return node == rhs.node;
}
template<typename T>
bool Iterator<T>::operator!=(const Iterator& rhs) const
{
return node != rhs.node;
}
}
List.h
#pragma once
#include "Iterator.h"
namespace Util
{
template<typename T>
class List
{
public:
typedef Iterator<T> Iterator;
typedef Node<T> Node;
List();
~List();
// Capacity
bool empty() const;
int size() const;
// Modifiers
void push_back(const T&);
void push_front(const T&);
void pop_back();
void pop_front();
Iterator erase(Iterator it);
// Element access
Iterator begin() const;
Iterator end() const;
private:
Node* head;
int list_size;
};
template<typename T>
List<T>::List() : list_size(0)
{
head = new Node();
}
template<typename T>
List<T>::~List()
{
while (!empty()) pop_back();
delete head;
}
template<typename T>
bool List<T>::empty() const
{
return head->next == head;
}
template<typename T>
int List<T>::size() const
{
return list_size;
}
template<typename T>
void List<T>::push_back(const T& t)
{
Node* n = new Node(t);
n->next = head;
n->prev = head->prev;
head->prev->next = n;
head->prev = n;
++list_size;
}
template<typename T>
void List<T>::push_front(const T& t)
{
Node* n = new Node(t);
n->prev = head;
n->next = head->next;
head->next->prev = n;
head->next = n;
++list_size;
}
template<typename T>
void List<T>::pop_back()
{
if (head->prev == head) return;
delete head->prev;
--list_size;
}
template<typename T>
void List<T>::pop_front()
{
if (head->next == head) return;
delete head->next;
--list_size;
}
template<typename T>
typename List<T>::Iterator List<T>::erase(Iterator it)
{
if (it.node == head) return it;
Node* n = it.node->next;
delete it.node;
--list_size;
return Iterator(n);
}
template<typename T>
typename List<T>::Iterator List<T>::begin() const
{
return Iterator(head->next);
}
template<typename T>
typename List<T>::Iterator List<T>::end() const
{
return Iterator(head);
}
}
Edit: after updating the code based on the comments I received. Going through the list and erasing, only erases every other element; since the loop is incrementing the iterator and erase makes the iterator's current object iterator's next object. Is this how it is in the standard as well?
for (Util::List<int>::Iterator it = list.begin(); it != list.end(); ++it)
{
it = list.erase(it);
}
Old list: 0 1 2 3 4 5 6 7 8 9
After erasing: 1 3 5 7 9
Please do not complain about rule of five and things unrelated to the question. I haven't gotten to every part yet. My justification of making an edit over posting a new question is that the edit is still about how to reconstruct the iterator correctly after erase.
As some people already mentioned, erase typically returns a new, valid iterator, if that is possible/feasible for the container.
You can define the semantics as you would like, but typically you would erase the element by pointing prev->next to next and next->prev to prev, then deallocate the node, and return an iterator to next. You could also return an iterator to prev, but that results in several counter-intuitive behaviors, such as having to advance the iterator if you are doing an operation on some sort of range. Returning an iterator to next, just lets you delete ranges with while(foo(it)) it = c.erase(it);
In that case you of course don't increment the iterator anymore, unless you wan t to skip every other element.

How to initialize values of Singly Linked List with constructor [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I have to create a constructor that allows a new linked list to be populated with ten consecutive values, starting at 0. Then I need to print the list! So i want to check if the functions I wrote for those are ok. Thanks!!
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
template <typename E> class SLinkedList; // forward declaration to be used when declaring SNode
template <typename E>
class SNode {
private:
E elem;
SNode<E> *next;
friend class SLinkedList<E>;
};
template <typename E>
class SLinkedList {
public:
SLinkedList();
SLinkedList(SNode<E>* v); //What I need help with
~SLinkedList();
bool empty() const;
E& front();
void printList(SLinkedList<E> &list); //what i need help with
void addFront(const E& e);
void removeFront();
int size() const;
private:
SNode<E>* head;
int n; // number of items
};
template <typename E>
SLinkedList<E>::SLinkedList() // constructor
: head(NULL), n(0) { }
template <typename E>
SLinkedList<E>::SLinkedList(SNode<E>* v){ //WHat I Need Help With
SNode<E>* v = new SNode<E>;
for (int i = 0; i < 10; i++)
v->elem = i;
}
template <typename E>
bool SLinkedList<E>::empty() const
{
return head == NULL; // can also use return (n == 0);
}
template <typename E>
E& SLinkedList<E>::front()
{
if (empty()) throw length_error("empty list");
return head->elem;
}
template <typename E>
SLinkedList<E>::~SLinkedList()
{
while (!empty()) removeFront();
}
template<typename E>
void SLinkedList<E>::printList(SLinkedList<E> &list) //What I need help with
{
for (int i = 0; i < list.size(); i++)
{
cout << list << " ";
}
cout << endl;
}
template <typename E>
void SLinkedList<E>::addFront(const E& e) {
SNode<E>* v = new SNode<E>; // create new node
v->elem = e; // store data
v->next = head; // head now follows v
head = v; // v is now the head
n++;
}
template <typename E>
void SLinkedList<E>::removeFront() {
if (empty()) throw length_error("empty list");
SNode<E>* old = head;
head = old->next;
delete old;
n--;
}
template <typename E>
int SLinkedList<E>::size() const {
return n;
}
thanks in advance for any help or suggestions! It is just these two functions that i am not sure about.
Try something more like this:
#include <iostream>
#include <string>
#include <stdexcept>
#include <initializer_list> // C++11 and later only
template <typename E>
class SLinkedList {
public:
SLinkedList();
SLinkedList(const E *vals, int num_vals);
SLinkedList(std::initializer_list<E> vals); // C++11 and later only
~SLinkedList();
bool empty() const;
int size() const;
E& front();
void addFront(const E &e);
void removeFront();
void printList() const;
private:
class SNode
{
public:
E elem;
SNode *next;
SNode(const E &e, SNode *n = NULL);
};
SNode* head;
int n; // number of items
};
template <typename E>
SLinkedList<E>::SNode::SNode(const E &e, SLinkedList<E>::SNode *n)
: elem(e), next(n) { }
template <typename E>
SLinkedList<E>::SLinkedList()
: head(NULL), n(0) { }
template <typename E>
SLinkedList<E>::SLinkedList(const E *vals, int num_vals)
: head(NULL), n(0)
{
for (int i = num_vals-1; i >= 0; --i)
addFront(vals[i]);
/* alternatively:
SNode **ptr = &head;
for (int i = 0; i < num_vals; ++i)
{
*ptr = new SNode(vals[i]);
++n;
ptr = &((*ptr)->next);
}
*/
}
template <typename E>
SLinkedList<E>::SLinkedList(std::initializer_list<E> vals)
: head(NULL), n(0)
{
const E *begin = vals.begin(), *iter = vals.end();
while (iter != begin)
addFront(*(--iter));
/* alternatively:
const E *iter = vals.begin(), *end = vals.end();
SNode **ptr = &head;
while (iter != end)
{
*ptr = new SNode(*iter);
++n;
ptr = &((*ptr)->next);
}
*/
}
template <typename E>
SLinkedList<E>::~SLinkedList()
{
while (head)
removeFront();
}
template <typename E>
bool SLinkedList<E>::empty() const
{
return (!head);
}
template <typename E>
int SLinkedList<E>::size() const
{
return n;
}
template <typename E>
E& SLinkedList<E>::front()
{
if (!head) throw std::length_error("empty list");
return head->elem;
}
template<typename E>
void SLinkedList<E>::printList() const
{
SNode *p = head;
while (p)
{
std::cout << p->elem << " ";
p = p->next;
}
std::cout << std::endl;
}
template <typename E>
void SLinkedList<E>::addFront(const E& e)
{
head = new SNode(e, head);
++n;
}
template <typename E>
void SLinkedList<E>::removeFront()
{
SNode* old = head;
if (!old) throw std::length_error("empty list");
head = old->next;
--n;
delete old;
}
Live Demo

Empty Dynamic List

I've created a simple dynamic template list and i'm having some issue clearing the entire list.
List.h
#ifndef LIST_H
#define LIST_H
#include <Node.h>
template <class T> class List
{
public:
typedef Node<T> node_type;
typedef node_type* node_pointer;
typedef T data_type;
typedef T& reference_type;
List();
void push_back(data_type);
reference_type at(int);
void clear();
void swap(int,int);
int size();
private:
int list_size = 0;
node_pointer head, tail;
};
template <class T> List<T>::List()
{
head=NULL;
tail=NULL;
}
template <class T> void List<T>::push_back(data_type data)
{
if(head == NULL) {
head = new node_type(data);
tail = head;
} else {
node_pointer temp = new node_type(data);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
list_size++;
}
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
node_pointer pointer=head;
for(int i=0; i<x; i++)
pointer=pointer->getNext();
return pointer->getData();
}
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
for(int i=0; i<list_size; i++) {
node_pointer temp = pointer;
pointer=pointer->getNext();
delete(temp);
}
head=NULL;
list_size=0;
}
template <class T> void List<T>::swap(int x, int y)
{
data_type buffer=at(x);
at(x)=at(y);
at(y)=buffer;
}
template <class T> int List<T>::size()
{
return list_size;
}
#endif // LIST_H
Node.h
template <class T> class Node
{
public:
typedef T data_type;
typedef T& reference_type;
Node(data_type _data);
void setData(data_type);
void setNextNull();
void setNext(Node*);
reference_type getData();
Node* getNext();
private:
data_type data;
Node* next;
};
template <class T> Node<T>::Node(data_type _data) : data(_data)
{
setNextNull();
}
template <class T> void Node<T>::setData(data_type _data)
{
data=_data;
}
template <class T> void Node<T>::setNextNull()
{
next=NULL;
}
template <class T> void Node<T>::setNext(Node* _next)
{
next=_next;
}
template <class T> typename Node<T>::reference_type Node<T>::getData()
{
return data;
}
template <class T> typename Node<T>::Node* Node<T>::getNext()
{
return next;
}
If I clear the list calling the "clear" method I get all sorts of errors in almost every other method, but if I use the version below the list works perfectly.
template <class T> void List<T>::clear()
{
head=NULL;
tail=NULL;
list_size=0;
}
The problem only appears if I use the delete function to clear memory. How can I solve this issue?
Your code is very dangerious, because you skipped important checks. Try to use following implementation of at():
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
if (x < 0 || x >= list_size || list_size <= 0)
return DATA_WITH_ERROR_FLAG; // since you return data instead of pointer,
// you can't return NULL here
// (you need special constant for error status
// or support it another way)
node_pointer pointer=head;
for(int i=0; i<x; i++)
{
if (!pointer)
return DATA_WITH_ERROR_FLAG;
pointer=pointer->getNext();
}
if (!pointer)
return DATA_WITH_ERROR_FLAG;
return pointer->getData();
}
After it you have to add checks after each at() call. For example, you have to modify swap() to make it safe too:
template <class T> void List<T>::swap(int x, int y)
{
data_type v1=at(x);
data_type v2=at(y);
if (v1 == DATA_WITH_ERROR_FLAG || v2 == DATA_WITH_ERROR_FLAG)
return; // and somehow set error flag!
data_type t=v1;
v1 = v2;
v2 = t;
}
I.e. you need to check correctness everywhere if you don't like such problems. And it is necessary to support returninig of error status to simplify analysis of errors.
Change your clear() method to this:
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
while (pointer != NULL) {
node_pointer temp = pointer-getNext();
delete pointer;
pointer = temp;
}
head=NULL;
tail=NULL;
list_size=0;
}
You have a memory leak in your code. You don't delete all the list by simply pointing head and tail to NULL.
The best way to do this is to create a delete() function then loop through the whole list while it is not empty and delete node by node.
void deleteHead()
{
if(head != NULL)
{
node *temp = head;
head = head->next;
delete temp;
size--;
}
}
bool isEmpty()
{
return head==NULL;
//return size == 0; <-- this is ok as well.
}
void clear()
{
while(! isEmpty())
{
deleteHead();
}
tail = head; //head = NULL
}

Template LinkedList class with nested class

I'm trying to implement a linked list with a template class LList and Nested Iterator and Node classes. Here's the code:
template <typename T1>
class LList
{
public:
class Iterator
{
public:
Iterator();
T1 get() const;
void next();
void previous();
bool equals(Iterator iter) const;
private:
Node* position;
LList* container;
};
LList();
~LList();
void pushBack(T1 data);
Iterator begin();
Iterator end();
void insert (Iterator iter, T1 data);
Iterator erase(Iterator Iter);
private:
class Node
{
public:
Node(T1 data);
private:
T1 data;
Node* ptr_next;
Node* ptr_prev;
};
Node* ptr_first;
Node* ptr_last;
};
template <typename T1>
LList<T1>::Node::Node(T1 data)
{
this->data = data;
ptr_next = 0;
ptr_prev =0;
}
template <typename T1>
LList<T1>::Iterator::Iterator()
{
position = 0;
container = 0;
}
template <typename T1>
T1 LList<T1>::Iterator::get() const
{
return position->data;
}
template <typename T1>
void LList<T1>::Iterator::next()
{
if(position == container->ptr_last)
{
position = container->ptr_first;
}
else
{
position = position->ptr_next;
}
}
template <typename T1>
void LList<T1>::Iterator::previous()
{
if(!position)
{
position = container->ptr_last;
}
else
{
position = position->ptr_prev;
}
}
template <typename T1>
bool LList<T1>::Iterator::equals(Iterator iter) const
{
return position == iter.position;
}
template <typename T1>
LList<T1>::LList()
{
ptr_first = 0;
ptr_last = 0;
}
template <typename T1>
LList<T1>::~LList()
{
while (ptr_first)
{
Node* tmp = ptr_first;
ptr_first = ptr_first->ptr_next;
delete tmp;
tmp = 0;
}
}
template <typename T1>
void LList<T1>::pushBack(T1 data)
{
Node* new_node = new Node(data);
if(ptr_first==0)
{
ptr_first = new_node;
ptr_last = new_node;
}
else
{
ptr_last->ptr_next = new_node;
new_node->ptr_prev = ptr_last;
ptr_last = new_node;
}
}
template <typename T1>
Iterator LList<T1>::begin()
{
Iterator iter;
iter.positon = ptr_first;
iter.container = this;
return iter;
}
template <typename T1>
Iterator LList<T2>::end()
{
Iterator iter;
iter.position = ptr_last;
iter.container = this;
return iter;
}
template <typename T1>
void LList<T1>::insert(Iterator iter, T1 data)
{
if (iter.position == 0)
{
pushBack(data);
return;
}
Node* before;
Node* after;
after = iter.position;
before = iter.position->ptr_prev;
Node* new_node = new Node(data);
after->ptr_prev = new_node;
if (before == 0) ptr_first = new_node;
else before->ptr_next = new_node;
new_node->ptr_prev = before;
new_node->ptr_next = after;
}
template <typename T1>
Iterator LList<T1>::erase(Iterator iter)
{
Node* after = iter.position->ptr_next;
Node* before = iter.position->ptr_prev;
Node* remove = iter.position;
if (remove == ptr_first) ptr_first = after;
else before->ptr_next = after;
if (remove == ptr_last) ptr_last = before;
else after->ptr_prev = before;
delete remove;
remove = 0;
}
I've seen how do it without nested classes but I need to do it with a nested class.
Any help on why it doesn't compile will help :) Thanks.
Well, Iterator is the name of a nested class, so when you use it in the definition of a member function of your LList class template as the return type, you have to fully qualify it (and add the typename disambiguator to tell the compiler that what follows the :: shall be parsed as the name of a type).
For instance:
template <typename T1>
typename LList<T1>::Iterator LList<T1>::erase(Iterator iter)
// ^^^^^^^^^^^^^^^^^^^^
There are several instances of this error, so you will have to fix all of them.
You are also referring to class Node before its definition appears inside LList. Therefore, you should have a forward declaration for it:
template <typename T1>
class LList
{
class Node;
// ^^^^^^^^^^^
// Forward declaration for Node
public:
// ...
class Iterator
{
// ...
Node* position; // <== Now this is OK because of the forward declaration
// ...
};
There are different error :
The first is that you use Node into the Iterator class, but you need to declare Node before it :
template <typename T1>
class LList
{
private:
class Node
{
public:
Node(T1 data);
private:
T1 data;
Node* ptr_next;
Node* ptr_prev;
};
Node* ptr_first;
Node* ptr_last;
public:
LList();
~LList();
void pushBack(T1 data);
class Iterator
{
public:
Iterator();
T1 get() const;
void next();
void previous();
bool equals(Iterator iter) const;
private:
Node* position;
LList* container;
};
Iterator begin();
Iterator end();
void insert (Iterator iter, T1 data);
Iterator erase(Iterator Iter);
};
That is the first thing.
The second is that Iterator is a nested type, so you need to be more specific when you return un object of this type :
template <typename T1>
typename LList<T1>::Iterator LList<T1>::begin()
And the last error is :
template <typename T1>
Iterator LList<T2>::end()
Here is the correct lign :
template <typename T1>
typename LList<T1>::Iterator LList<T1>::end()
// ^^^^^^^^^^^^^^^^^ ^^