How to do right template outputs in c++ - c++

i have this error in MSVS project, in this part of code
ostream& getStream(ostream& out)
{
for (Node* temp = head; temp; temp = temp->next)
out << temp->info << " ";
return out;
}
Error C2679 binary"<<": no operator was found that accepts the right operand of type " T " (or there is no acceptable conversion)
#pragma once
#ifndef _LIST_H_
#define _LIST_H_
#include <iostream>
using namespace std;
template <class T>
class MyList
{
protected :
struct Node
{
T info;
Node* next;
Node(T info, Node* next = 0) :
info(info),
next(next)
{}
};
Node* head;
ostream& getStream(ostream& out)
{
for (Node* temp = head; temp; temp = temp->next)
out << temp->info << " ";
return out;
}
public:
MyList();
~MyList();
template <class T1>
friend ostream& operator<<(ostream& os, MyList<T1>& list);
void Insert(T info, int index);
int Count();
void Remove(int index);
void PopFront();
void PushFront(T Data);
void PopBack();
void PushBack(T Data);
};
template <class T>
MyList<T>::MyList():
head(0)
{}
template <class T>
MyList<T>::~MyList()
{
while (head != NULL)
{
Node* help = head->next;
delete head;
head = help;
}
}
template <class T>
ostream& operator<<(ostream& out, MyList<T>& list)
{
return list.getStream(out);
}
template <class T>
void MyList<T>::Insert(T info, int index)
{
if (Count() < index || index < 0) throw 1;
if (index == 0)
{
head = new Node(info, head);
return;
}
Node* current = head;
for (int i = 1; i < index; current = current->next, i++);
current->next = new Node(info, current->next);
}
template <class T>
void MyList<T>::Remove(int index)
{
if (Count() <= index || index < 0) throw 1;
if (index == 0)
{
Node* help = head->next;
delete head;
head = help;
return;
}
Node* current = head;
for (int i = 1; i < index; current = current->next, i++);
Node* help = current->next;
current->next = help->next;
delete help;
}
template <class T>
void MyList<T>::PopFront()
{
if (head == 0) return;
Node* help = head;
head = head->next;
delete help;
}
template<class T>
void MyList<T>::PushFront(T Data)
{
head = new Node(Data, head);
}
template<class T>
void MyList<T>::PopBack()
{
if (head == 0)return;
if (Count() == 1)
{
delete head;
head = 0;
}
Node* curr;
for (curr = head; curr->next->next != 0; curr = curr->next);
delete curr->next;
curr->next = 0;
}
template<class T>
void MyList<T>::PushBack(T Data)
{
Node* curr;
for (curr = head; curr->next != 0; curr = curr->next);
curr->next = new Node(Data);
}
template <class T>
int MyList<T>::Count()
{
int count = 0;
for (Node* current = head; current != NULL; current = current->next, count++);
return count;
}
#endif // !_LIST_H_
this is declaration of my class
i have no ideas how to fix it,
big thank to you if you will try to help me
sory if have bad description, im only starting

one of descendant of my class have bad implementation of operator<<, and that class jump me to this problem

Related

"blocks are indirectly lost in loss record.." valgrind error - cpp

I am trying to figure out what is wrong with my cpp code, and i need your help!
valgrind Output:
the error occurs here (in the test file):
list = list.apply(getLen);
the function getLen:
string getLen(string str)
{
return std::to_string(str.length());
}
the generic function apply:
template<class T>
template<class Operation>
SortedList<T> SortedList<T>::apply(Operation operation) const{//TODO: 6 blocks are indirectly lost.
Node<T>* current_node_to_check = head;
SortedList<T> new_sorted_list;
for (int i = 0; i < list_length; ++i) {
T result = operation(current_node_to_check->info);
new_sorted_list.insert(result);
current_node_to_check = current_node_to_check->next;
}
return new_sorted_list;
}
the Node struct implementation:
template<class T>
struct Node{
T info;
Node<T>* next;
explicit Node(const T& new_info) : info(new_info), next(nullptr){}
};
the test file:
#include <iostream>
#include "SortedList.h"
#include "examDetails.h"
using std::cout;
using std::endl;
using std::string;
using namespace mtm;
#define TEST(num) cout << endl << "TEST " << (num) << endl;
string getLen(string str)
{
return std::to_string(str.length());
}
bool isTrollLink(const ExamDetails& exam) {
return (exam.getLink().find("tinyurl") != string::npos);
}
template<class T>
void printList(SortedList<T> list) {
for (auto it = list.begin(); !(it == list.end()); ++it) {
cout << *it << endl;
}
cout << endl;
}
int main()
{
.
.
.
TEST("1.5")
SortedList<string> lst1 = SortedList<string>();
lst1.insert("Charlie");
lst1.insert("Bob");
lst1.insert("Alice");
lst1.insert("Donald");
printList(lst1);
TEST("1.6")
SortedList<ExamDetails> lst2;
lst2.insert(exam1);
lst2.insert(exam2);
printList(lst2);
TEST("1.7")
SortedList<string> lst3 = lst1;
printList(lst3);
TEST("1.8")//TODO: 6 blocks are indirectly lost.
lst3 = lst3.apply(getLen);
printList(lst3);
TEST("1.9")
lst3.remove(lst3.begin());
printList(lst3);
TEST("1.10")
SortedList<ExamDetails> lst4 = lst2.filter(isTrollLink);
printList(lst2);
cout << "----------" << endl;
printList(lst4);
return 0;
}
the generic class file:
#ifndef NEW_SORTED_LIST_SORTEDLIST_H
#define NEW_SORTED_LIST_SORTEDLIST_H
#include <stdexcept>
using std::cout;
using std::endl;
namespace mtm {
template<class T>
struct Node{
T info;
Node<T>* next;
explicit Node(const T& new_info) : info(new_info), next(nullptr){}
};
template<class T>
class SortedList {
private:
Node<T>* head;
int list_length;
static const int empty = 0;
void deleteNodes();
public:
class const_iterator;
SortedList();
~SortedList();
SortedList(const SortedList &to_copy);
SortedList& operator=(const SortedList &to_assign);
void insert(const T &to_insert);
void remove(const const_iterator& iterator);
int length() const;
template<class Condition>
SortedList filter(Condition condition) const;
template<class Operation>
SortedList apply(Operation operation) const;
const_iterator begin() const;
const_iterator end() const;
};
template<class T>
class SortedList<T>::const_iterator{
const SortedList<T>* sortedListPointer;
int index;
const_iterator(const SortedList<T>* sortedListPointer, int index) : sortedListPointer(sortedListPointer),
index(index){}
friend class SortedList<T>;
static const int first = 1;
public:
const_iterator(const const_iterator&) = default;
const_iterator& operator=(const const_iterator&) = default;
const T& operator*(){
if (index > sortedListPointer->length()+1 || index<0){
throw std::out_of_range("error: iterator out of range");//TODO
}
Node<T>* current = sortedListPointer->head;
for (int i = 1; i < index; ++i) {
current = current->next;
}
return current->info;
}
const_iterator& operator++() {
++index;
if (index > sortedListPointer->length()+1){
throw std::out_of_range("error: iterator out of range");//TODO
}
return *this;
}
const_iterator operator++(int){
SortedList<T>::const_iterator result = *this;
++*this;
return result;
}
bool operator==(const const_iterator& it) const{
return (index == it.index);
}
};
template<class T>
typename SortedList<T>::const_iterator SortedList<T>::begin() const{
return const_iterator(this, const_iterator::first);
}
template<class T>
typename SortedList<T>::const_iterator SortedList<T>::end() const{
return const_iterator(this, this->length()+1);
}
template<class T>
SortedList<T>::SortedList() : head(nullptr), list_length(empty){}
template<class T>
SortedList<T>::~SortedList() {
deleteNodes();
}
template<class T>
SortedList<T>::SortedList(const SortedList& to_copy){
Node<T>* current_to_copy = to_copy.head;
Node<T>* current = nullptr;
Node<T>* new_head;
if (to_copy.list_length == 0){
return;
}else{
Node<T>* new_node = new Node<T>(current_to_copy->info);
//exception
//new_node->info = current_to_copy->info;
//new_node->next = nullptr;
current = new_node;
current_to_copy = current_to_copy->next;
new_head = current;
}
while (current_to_copy){
Node<T>* new_node = new Node<T>(current_to_copy->info);
//exception
//new_node->info = current_to_copy->info;
//new_node->next = nullptr;
current->next = new_node;
current = current->next;
current_to_copy = current_to_copy->next;
}
list_length = to_copy.list_length;
head = new_head;
}
template<class T>
void SortedList<T>::deleteNodes(){
if (list_length == empty){
head = nullptr;
return;
}
Node<T>* current = head->next;
for (int i = 1; i < list_length; ++i) {
Node<T>* previous = head;
Node<T>* temp = current->next;
delete current;
current = temp;
previous->next = current;
}
delete head;
head = nullptr;
list_length = empty;
}
template<class T>
SortedList<T>& SortedList<T>::operator=(const SortedList &to_assign){
if (this == &to_assign){
return *this;
}
head = nullptr;
Node<T>* current_to_assign = to_assign.head;
Node<T>* current;
Node<T>* new_head;
if (current_to_assign){
Node<T>* first_node = new Node<T>(current_to_assign->info);
current = first_node;
current_to_assign = current_to_assign->next;
new_head = first_node;
}else{
deleteNodes();
head = nullptr;
return *this;
}
while (current_to_assign){
Node<T>* new_node = new Node<T>(current_to_assign->info);
current->next = new_node;
current = current->next;
current_to_assign = current_to_assign->next;
}
head = new_head;
list_length = to_assign.list_length;
return *this;
}
template<class T>
void SortedList<T>::insert(const T &to_insert){
Node<T>* new_node = new Node<T>(to_insert);
Node<T>* current = head;
if (!current){
head = new_node;
list_length++;
return;
}
Node<T>* previous = head;
if (current->info < to_insert){
current = current->next;
}else{
new_node->next = current;
head = new_node;
list_length++;
return;
}
while (current){
if (current->info < to_insert){
current = current->next;
previous = previous->next;
}else{
new_node->next = current;
previous->next = new_node;
list_length++;
return;
}
}
previous->next = new_node;
list_length++;
}
template<class T>
void SortedList<T>::remove(const SortedList<T>::const_iterator& iterator){
if (list_length == 1){
list_length--;
delete head;
}
int index = iterator.index;
if (index == 1){
Node<T>* temp = head->next;
delete head;
head = temp;
list_length--;
return;
}
Node<T>* current = head;
Node<T>* previous = nullptr;
for (int i = 1; i < index-1; ++i) {
if ((i+1) == index-1){
previous = current;
}
current = current->next;
}
previous->next = current->next;
delete current;//TODO destructor(?)
list_length--;
}
template<class T>
int SortedList<T>::length() const{
return list_length;
}
template<class T>
template<class Condition>
SortedList<T> SortedList<T>::filter(Condition condition) const{
Node<T>* current_node_to_check = head;
SortedList<T> new_sorted_list;
for (int i = 0; i < list_length; ++i) {
if (condition(current_node_to_check->info)){
new_sorted_list.insert(current_node_to_check->info);
}
current_node_to_check = current_node_to_check->next;
}
return new_sorted_list;
}
template<class T>
template<class Operation>
SortedList<T> SortedList<T>::apply(Operation operation) const{//TODO: 6 blocks are indirectly lost.
Node<T>* current_node_to_check = head;
SortedList<T> new_sorted_list;
for (int i = 0; i < list_length; ++i) {
T result = operation(current_node_to_check->info);
new_sorted_list.insert(result);
current_node_to_check = current_node_to_check->next;
}
return new_sorted_list;
}
}
#endif //NEW_SORTED_LIST_SORTEDLIST_H
without the test 1.8, the code works great with no errors at all!
What should I do to fix it?
thanks
You allocated a SortedList<string> object in main() which allocated memory and never freed it.
The other blocks belong to the std::string objects inside the list. They are only lost because the list holding them lost track of them.
When doing your analysis, don't worry about the 6 indirectly lost blocks, focus on the one directly lost one.
Almost certainly this is a violation of the "Rule of Five". Your SortedList does an allocation in its constructor and doesn't properly manage that allocation in its move-assignment operator.
Looking at your code in the copy assignment operator, this line is causing the leak
head = nullptr;
It shouldn't be needed, you later call deleteNodes() which will do that anyway, and by erasing head beforehand you prevent deleteNodes() from doing its work.

Deleting at some position in a double linked list

I am having some trouble with this function I wrote to delete at some position in a double linked list. I feel like I am leaking memory and I am not doing this property for a double linked list.
Here is the code:
template <class T>
void DoubleLinkedLists<T>::deletePosition(int pos) {
Node* prev = new Node;
Node* current = head;
for(int i = 1; i < pos; i++) {
prev = current;
current = current->next;
}
prev->next = current->next;
}
This is pretty much what I did for a single linked list so I know this is not right. If anyone has any suggestions on how to do this for a double linked list I would really appreciate it.
EDIT:
I think this works correctly now:
template <class T>
void DoubleLinkedLists<T>::deletePosition(int pos) {
Node* temp = nullptr;
Node* current = head;
for(int i = 1; i < pos; i++) {
temp = current;
current = current->next;
}
temp->previous = current->previous;
temp->next = current->next;
}
Here is the entire code:
#ifndef DoubleLinkedLists_h
#define DoubleLinkedLists_h
template <class T>
class DoubleLinkedLists {
private:
struct Node {
T data;
Node* next;
Node* previous;
};
Node* head;
Node* tail;
public:
// Constructors
DoubleLinkedLists() : head(nullptr), tail(nullptr) {} // empty constructor
DoubleLinkedLists(DoubleLinkedLists const& value); // copy constructor
DoubleLinkedLists<T>(DoubleLinkedLists<T>&& move) noexcept; // move constuctor
DoubleLinkedLists<T>& operator=(DoubleLinkedLists&& move) noexcept; // move assignment operator
~DoubleLinkedLists(); // destructor
// Overload operators
DoubleLinkedLists& operator=(DoubleLinkedLists const& rhs);
friend std::ostream& operator<<(std::ostream& str, DoubleLinkedLists<T> const& data) {
data.display(str);
return str;
}
// Member functions
void swap(DoubleLinkedLists& other) noexcept;
void push(const T& theData);
void push(T&& theData);
void display(std::ostream& str) const;
void insertHead(const T& theData);
void insertTail(const T& theData);
void insertPosition(int pos, const T& theData);
void deleteHead();
void deleteTail();
void deletePosition(int pos);
bool search(const T& x);
};
template <class T>
DoubleLinkedLists<T>::DoubleLinkedLists(DoubleLinkedLists const& value) : head(nullptr), tail(nullptr) {
for(Node* loop = value->head; loop != nullptr; loop = loop->next) {
push(loop->data);
}
}
template <class T>
DoubleLinkedLists<T>::DoubleLinkedLists(DoubleLinkedLists<T>&& move) noexcept : head(nullptr), tail(nullptr) {
move.swap(*this);
}
template <class T>
DoubleLinkedLists<T>& DoubleLinkedLists<T>::operator=(DoubleLinkedLists<T> &&move) noexcept {
move.swap(*this);
return *this;
}
template <class T>
DoubleLinkedLists<T>::~DoubleLinkedLists() {
while(head != nullptr) {
deleteHead();
}
}
template <class T>
void DoubleLinkedLists<T>::swap(DoubleLinkedLists<T> &other) noexcept {
using std::swap;
swap(head,other.head);
swap(tail,other.tail);
}
template <class T>
void DoubleLinkedLists<T>::push(const T& theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->previous = tail;
if(head == nullptr) {
head = newNode;
}
else {
tail->next = newNode;
}
tail = newNode;
}
template <class T>
void DoubleLinkedLists<T>::push(T&& theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->previous = tail;
if(head == nullptr) {
head = newNode;
}
else {
tail->next = newNode;
}
tail = newNode;
}
template <class T>
void DoubleLinkedLists<T>::display(std::ostream &str) const {
for(Node* loop = head; loop != nullptr; loop = loop->next) {
str << loop->data << "\t";
}
str << "\n";
}
template <class T>
void DoubleLinkedLists<T>::insertHead(const T &theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->next = head;
head->previous = newNode;
head = newNode;
}
template <class T>
void DoubleLinkedLists<T>::insertTail(const T &theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->previous = tail;
tail->next = newNode;
tail = newNode;
}
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T &theData) {
if (pos < 0) {
throw std::invalid_argument("pos is not a valid index");
}
Node* current = head;
Node* previous = nullptr;
while(pos-- > 0) {
if(!current) {
throw std::invalid_argument("pos is not a valid index");
}
previous = current;
current = current->next;
}
Node* newNode = new Node;
newNode->data = theData;
newNode->previous = previous;
newNode->next = current;
if(newNode->previous) {
newNode->previous->next = newNode;
}
else {
head = newNode;
}
if(newNode->next) {
newNode->next->previous = newNode;
}
else {
tail = newNode;
}
}
template <class T>
void DoubleLinkedLists<T>::deleteHead() {
if (head != nullptr) {
Node* old = head;
head = head->next;
delete old;
}
else {
throw std::invalid_argument("the list is empty!");
}
}
template <class T>
void DoubleLinkedLists<T>::deleteTail() {
if(head != nullptr) {
Node* prev = nullptr;
Node* current = head;
while(current->next != nullptr) {
prev = current;
current = current->next;
}
tail = prev;
prev->next = nullptr;
delete current;
}
else {
throw std::invalid_argument("The list is already empty, nothing to delete.");
}
}
template <class T>
void DoubleLinkedLists<T>::deletePosition(int pos) {
Node* temp = nullptr;
Node* current = head;
for(int i = 1; i < pos; i++) {
temp = current;
current = current->next;
}
temp->previous = current->previous;
temp->next = current->next;
}
template <class T>
bool DoubleLinkedLists<T>::search(const T &x) {
Node* current = head;
while(current != nullptr) {
if(current->data == x) {
return true;
}
current = current->next;
}
return false;
}
#endif /* DoubleLinkedLists_h */
And here is the main.cpp file that tests it:
#include <iostream>
#include "DoubleLinkedLists.h"
int main(int argc, const char * argv[]) {
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Double Linked List //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
DoubleLinkedLists<int> obj;
obj.push(2);
obj.push(4);
obj.push(6);
obj.push(8);
obj.push(10);
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Displaying All nodes---------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"----------------Inserting At Start----------------";
std::cout<<"\n--------------------------------------------------\n";
obj.insertHead(50);
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"-----------------Inserting At End-----------------";
std::cout<<"\n--------------------------------------------------\n";
obj.insertTail(20);
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"-------------Inserting At Particular--------------";
std::cout<<"\n--------------------------------------------------\n";
obj.insertPosition(5,60);
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"----------------Deleting At Start-----------------";
std::cout<<"\n--------------------------------------------------\n";
obj.deleteHead();
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"----------------Deleting At End-----------------";
std::cout<<"\n--------------------------------------------------\n";
obj.deleteTail();
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"--------------Deleting At Particular--------------";
std::cout<<"\n--------------------------------------------------\n";
obj.deletePosition(5);
std::cout << obj << std::endl;
std::cout << std::endl;
obj.search(8) ? printf("Yes"):printf("No");
return 0;
}
So you would need to do something like this. Note that your code does not handle the case of an index out of range (i.e. the position specified is either negative or is longer the list). It looked like you don't maintain a count of your list length (in the linked code) so I added a check for current != nullptr into the for loop as well as after the for loop to handle the case of the pos being longer than the list. In that case, now the code will do nothing, but you could throw an out of range exception or something like that to indicate the invalid condition. In the case of removing the head you also need to take care to fix up the head pointer. I am assuming you might have a tail pointer as well, so you need to add checks to see if you are removing the tail and fix that up as well.
Note
I didn't compile this and so there may be a typo or two, but it should at least point you in the right direction.
void DoubleLinkedLists<T>::deletePosition(int pos) {
if (pos < 0) {} // Should do something in this case
Node* current = head;
// Added null check to keep from continuing past the end of the list
for(int i = 1; i < pos && current != nullptr; i++) {
current = current->next;
}
if (current != nullptr)
{
// If we are at the head, there isn't a previous
if (current != head)
{
current->previous->next = current->next;
}
else
{
// In this case, we are removing the head, need to reset head to the next Node
head = current->next;
}
if (current->next != nullptr)
{
current->next->previous = current->previous;
}
else if (current == tail)
{
// In this case we are removing the tail, need to reset tail pointer
tail = current->previous;
}
delete current; // Cleans up the node we are deleting
}
}

C++ Creating a Linked List With More Than 2 Fields per Node

So I am attempting to create a Linked List that can store books for a imaginative library. Within the linked list, each node should contain the branch of library, the author's name, the book's title, and the number of copies of said book.
I'm having difficulty creating a linked list with multiple fields per node. How would I go about it so that each node can store 3 separate strings and an integer, and then finally, a pointer to the next node?
Here is my current code.
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdexcept>
using namespace std;
template<typename T>
class Node
{
public:
T element;
Node<T>* next;
Node()
{
next = nullptr;
}
Node(T element) // Constructor
{
this->element = element;
next = nullptr;
}
};
template<typename T>
class Iterator : public std::iterator<std::forward_iterator_tag, T>
{
public:
Iterator(Node<T>* p)
{
current = p;
}
Iterator operator++() // Prefix ++
{
current = current->next;
return *this;
}
Iterator operator++(int dummy) // Postfix ++
{
Iterator temp(current);
current = current->next;
return temp;
}
T& operator*()
{
return current->element;
}
bool operator==(const Iterator<T>& iterator)
{
return current == iterator.current;
}
bool operator!=(const Iterator<T>& iterator)
{
return current != iterator.current;
}
private:
Node<T>* current;
};
template<typename T>
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList<T>& list);
virtual ~LinkedList();
void addFirst(T element);
void addLast(T element);
T getFirst() const;
T getLast() const;
T removeFirst() throw (runtime_error);
T removeLast();
void add(T element);
void add(int index, T element);
void clear();
bool contains(T element) const;
T get(int index) const;
int indexOf(T element) const;
bool isEmpty() const;
int lastIndexOf(T element) const;
void remove(T element);
int getSize() const;
T removeAt(int index);
T set(int index, T element);
Iterator<T> begin() const
{
return Iterator<T>(head);
}
Iterator<T> end() const
{
return Iterator<T>(tail->next);
}
private:
Node<T>* head;
Node<T>* tail;
int size;
};
template<typename T>
LinkedList<T>::LinkedList()
{
head = tail = nullptr;
size = 0;
}
template<typename T>
LinkedList<T>::LinkedList(const LinkedList<T>& list)
{
head = tail = nullptr;
size = 0;
Node<T>* current = list.head;
while (current != nullptr)
{
this->add(current->element);
current = current->next;
}
}
template<typename T>
LinkedList<T>::~LinkedList()
{
clear();
}
template<typename T>
void LinkedList<T>::addFirst(T element)
{
Node<T>* newNode = new Node<T>(element);
newNode->next = head;
head = newNode;
size++;
if (tail == nullptr)
tail = head;
}
template<typename T>
void LinkedList<T>::addLast(T element)
{
if (tail == nullptr)
{
head = tail = new Node<T>(element);
}
else
{
tail->next = new Node<T>(element);
tail = tail->next;
}
size++;
}
template<typename T>
T LinkedList<T>::getFirst() const
{
if (size == 0)
throw runtime_error("Index out of range");
else
return head->element;
}
template<typename T>
T LinkedList<T>::getLast() const
{
if (size == 0)
throw runtime_error("Index out of range");
else
return tail->element;
}
template<typename T>
T LinkedList<T>::removeFirst() throw (runtime_error)
{
if (size == 0)
throw runtime_error("No elements in the list");
else
{
Node<T>* temp = head;
head = head->next;
if (head == nullptr) tail = nullptr;
size--;
T element = temp->element;
delete temp;
return element;
}
}
template<typename T>
T LinkedList<T>::removeLast()
{
if (size == 0)
throw runtime_error("No elements in the list");
else if (size == 1)
{
Node<T>* temp = head;
head = tail = nullptr;
size = 0;
T element = temp->element;
delete temp;
return element;
}
else
{
Node<T>* current = head;
for (int i = 0; i < size - 2; i++)
current = current->next;
Node<T>* temp = tail;
tail = current;
tail->next = nullptr;
size--;
T element = temp->element;
delete temp;
return element;
}
}
template<typename T>
void LinkedList<T>::add(T element)
{
addLast(element);
}
template<typename T>
void LinkedList<T>::add(int index, T element)
{
if (index == 0)
addFirst(element);
else if (index >= size)
addLast(element);
else
{
Node<T>* current = head;
for (int i = 1; i < index; i++)
current = current->next;
Node<T>* temp = current->next;
current->next = new Node<T>(element);
(current->next)->next = temp;
size++;
}
}
template<typename T>
void LinkedList<T>::clear()
{
while (head != nullptr)
{
Node<T>* temp = head;
head = head->next;
delete temp;
}
tail = nullptr;
size = 0;
}
template<typename T>
T LinkedList<T>::get(int index) const
{
if (index < 0 || index > size - 1)
throw runtime_error("Index out of range");
Node<T>* current = head;
for (int i = 0; i < index; i++)
current = current->next;
return current->element;
}
template<typename T>
int LinkedList<T>::indexOf(T element) const
{
// Implement it in this exercise
Node<T>* current = head;
for (int i = 0; i < size; i++)
{
if (current->element == element)
return i;
current = current->next;
}
return -1;
}
template<typename T>
bool LinkedList<T>::isEmpty() const
{
return head == nullptr;
}
template<typename T>
int LinkedList<T>::getSize() const
{
return size;
}
template<typename T>
T LinkedList<T>::removeAt(int index)
{
if (index < 0 || index >= size)
throw runtime_error("Index out of range");
else if (index == 0)
return removeFirst();
else if (index == size - 1)
return removeLast();
else
{
Node<T>* previous = head;
for (int i = 1; i < index; i++)
{
previous = previous->next;
}
Node<T>* current = previous->next;
previous->next = current->next;
size--;
T element = current->element;
delete current;
return element;
}
}
// The functions remove(T element), lastIndexOf(T element),
// contains(T element), and set(int index, T element) are
// left as an exercise
#endif
Given a struct, such as
struct Book
{
std::string branch;
std::string author;
std::string title;
int copies;
};
A LinkedList<Book> would have all the data elements you want in each Node.

Linked List of linked lists trouble

I am having trouble implementing this with the class I have. So far as a linkedlist of type int or string it works great, but I am not sure how to navigate the list if I initialize it like
linkedlist<linkedlist<int>> nums;
From my program it seems that the head of each secondary list would be an entry in the primary, but my question is how would I navigate it?. For example how would I print all the values of each linkedlist, I am sure I am making this more difficult than it it, but any help would be appreciated.
/* Node Class */
template <typename T>
class Node {
public:
T data;
Node* next;
Node* previous;
Node(T data);
Node();
T getData();
};
template <typename T>
Node<T>::Node() {
this->next = NULL;
this->previous = NULL;
}
template <typename T>
Node<T>::Node(T data) {
this->data = data;
}
template <typename T>
T Node<T>::getData() {
return this->data;
}
/* Linked List: */
template <typename T>
class linkedlist {
private:
Node<T>* head;
Node<T>* tail;
int list_size;
public:
linkedlist();
T getHead();
T getTail();
int size();
void addnodetail(T);
void addnodehead(T);
void push(T);
T pop();
//T* peek();
bool isEmpty() const {
return head == NULL;
}
//T* get(int index);
void printlist();
void printListBackwards();
~linkedlist();
};
template <typename T>
linkedlist<T>::linkedlist() {
this->head = NULL;
this->tail = NULL;
this->list_size = 0;
}
template <typename T>
T linkedlist<T>::getHead() {
return this->head->data;
}
template <typename T>
T linkedlist<T>::getTail() {
return this->tail->data;
}
template <class T>
int linkedlist<T>::size() {
return this->list_size;
}
template <typename T>
void linkedlist<T>::addnodetail(T input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->tail->next = newnode;
newnode->previous = this->tail;
this->tail = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::addnodehead(T input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->head->previous = newnode;
newnode->next = this->head;
this->head = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::push(T input) {
this->addnodehead(input);
}
template <typename T>
T linkedlist<T>::pop() {
Node<T>* temp = this->head;
// T* temp = this->head;
this->head = this->head->next;
this->head->previous = NULL;
this->list_size = this->list_size - 1;
return temp->data;
}
/*
template <class T>
T* MyList<T>::peek() {
return this->head;
}
template <class T>
T* MyList<T>::get(int index) {
if (index == 0) {
return this->head;
} else if (index == this->list_size - 1) {
return this->tail;
} else if (index < 0 || index >= this->list_size) {
return NULL;
}
if (index < this->list_size / 2) {
T* temp = this->head;
int i = 0;
while (temp) {
if (i == index) { return temp; }
i++;
temp = temp->next;
}
} else {
T* temp = this->tail;
int i = this->list_size - 1;
while (temp) {
if (i == index) { return temp; }
i--;
temp = temp->previous;
}
}
return NULL;
}*/
template <typename T>
void linkedlist<T>::printlist() {
cout << "HEAD: ";
Node<T>* temp = this->head;
while(temp) {
cout << temp->data << " -> ";
temp = temp->next;
}
cout << "\b\b\b\b :TAIL" << endl;
}
template <class T>
void linkedlist<T>::printListBackwards() {
cout << "TAIL: ";
Node<T>* temp = this->tail;
while(temp) {
cout << temp->data << " -> ";
temp = temp->previous;
}
cout << "\b\b\b\b :HEAD" << endl;
}
template <typename T>
linkedlist<T>::~linkedlist() {
for(Node<T>* p;!isEmpty();){
p = head->next;
delete head;
head = p;
}
}
EDIT with copy constructor
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
#include <ctype.h>
using namespace std;
using namespace std;
/*struct AdjListNode
{
int dest;
struct AdjListNode* next;
};
// A structure to represent an adjacency list
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
int i;
for (i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// A utility function to print the adjacenncy list representation of graph
void printGraph(struct Graph* graph)
{
int v;
for (v = 0; v < graph->V; ++v)
{
struct AdjListNode* pCrawl = graph->array[v].head;
printf("\n Adjacency list of vertex %d\n head ", v);
while (pCrawl)
{
printf("-> %d", pCrawl->dest);
pCrawl = pCrawl->next;
}
printf("\n");
}
}
*/
/* Node Class */
template <typename T>
class Node {
public:
T data;
Node* next;
Node* previous;
Node(T data);
Node();
T getData();
};
template <typename T>
Node<T>::Node() {
this->next = NULL;
this->previous = NULL;
}
template <typename T>
Node<T>::Node(T data) {
this->data = data;
this->next = NULL;
}
template <typename T>
T Node<T>::getData() {
return this->data;
}
/* Linked List: */
template <typename T>
class linkedlist {
private:
Node<T>* head;
Node<T>* tail;
int list_size;
public:
linkedlist();
linkedlist(linkedlist& object);
T getHead();
T getTail();
int size();
void addtail(const T& input);
void addhead(const T& input);
void push(T);
T pop();
//T* peek();
bool isEmpty() const {
return head == NULL;
}
//T* get(int index);
void printlist();
void printListBackwards();
~linkedlist();
};
template <typename T>
linkedlist<T>::linkedlist() {
this->head = NULL;
this->tail = NULL;
this->list_size = 0;
}
template <typename T>
linkedlist<T>::linkedlist(linkedlist &object){
if(object.head == NULL){
head == NULL;
}
else {
head = new Node<T>(object.head->data);
Node<T>* temp = head;
Node<T>* objecthead = object.head;
Node<T>* current = objecthead;
while(current->next != NULL){
temp->next = new Node<T>(current->next->data);
current = current->next;
temp = temp->next;
}
}
}
template <typename T>
T linkedlist<T>::getHead() {
return this->head->data;
}
template <typename T>
T linkedlist<T>::getTail() {
return this->tail->data;
}
template <class T>
int linkedlist<T>::size() {
return this->list_size;
}
template <typename T>
void linkedlist<T>::addtail(const T& input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->tail->next = newnode;
newnode->previous = this->tail;
this->tail = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::addhead(const T& input) {
Node<T>* newnode = new Node<T>(input);
newnode->next = NULL;
newnode->previous = NULL;
if (this->head == NULL) {
this->head = newnode;
this->tail = this->head;
this->list_size = this->list_size + 1;
} else {
this->head->previous = newnode;
newnode->next = this->head;
this->head = newnode;
this->list_size = this->list_size + 1;
}
}
template <typename T>
void linkedlist<T>::push(T input) {
this->addhead(input);
}
template <typename T>
T linkedlist<T>::pop() {
Node<T>* temp = this->head;
if(temp != NULL){
this->head = this->head->next;
this->head->previous = NULL;
this->list_size = this->list_size - 1;
return temp->data;
}
else{
cout << "Error:Empty List!";
exit (EXIT_FAILURE);
}
}
/*
template <class T>
T* MyList<T>::peek() {
return this->head;
}
template <class T>
T* MyList<T>::get(int index) {
if (index == 0) {
return this->head;
} else if (index == this->list_size - 1) {
return this->tail;
} else if (index < 0 || index >= this->list_size) {
return NULL;
}
if (index < this->list_size / 2) {
T* temp = this->head;
int i = 0;
while (temp) {
if (i == index) { return temp; }
i++;
temp = temp->next;
}
} else {
T* temp = this->tail;
int i = this->list_size - 1;
while (temp) {
if (i == index) { return temp; }
i--;
temp = temp->previous;
}
}
return NULL;
}*/
template <typename T>
void linkedlist<T>::printlist() {
cout << "STACK" << endl;
cout << "-------------------" << endl;
Node<T>* temp = this->head;
while(temp) {
cout << "\t" << temp->data << endl;
temp = temp->next;
}
//cout << "\b\b\b\b :TAIL" << endl;
}
template <class T>
void linkedlist<T>::printListBackwards() {
cout << "TAIL: ";
Node<T>* temp = this->tail;
while(temp) {
cout << temp->data << " -> ";
temp = temp->previous;
}
cout << "\b\b\b\b :HEAD" << endl;
}
template <typename T>
linkedlist<T>::~linkedlist() {
for(Node<T>* p;!isEmpty();){
p = head->next;
delete head;
head = p;
}
}
#endif // LINKEDLIST_H

how to extract a list from a linked list in c++

I'm trying to implement those two functions "extract" and "deleteList" and I somehow can't get my head around it.
I know how a linked-list works but I'm new to programming and just can't figure out an algorithm. Could I ask for some tips?
I want the extract function to return a list of values that fulfill the predicate and remove those from the original list (thats why its passed as a reference).
I want the delete function to delete all those that are the same as those passed from the argument
My code looks like this:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct Node
{
T data;
Node* next;
};
template <typename T>
void showList(const Node<T>* head)
{
while(head->next != NULL)
{
cout<<head->data<<" ";
head = head->next;
}
cout<<endl;
}
template <typename T>
Node<T>* arrayToList(const T tab[], size_t size)
{
Node<T> *prev;
for(int i = size-1; i>=0 ; i--){
Node<T> *p = new Node<T>;
p->data = tab[i];
p->next = prev;
prev = p;
}
return prev;
}
template<typename T>
Node<T>* extract(Node<T>*& head, bool (*predicate)(const T&))
{
}
template <typename T>
void deleteList(Node<T>*& head)
{
//delete passed in
}
bool isEven(const int& n)
{
return n%2 == 0;
}
bool isLong(const string& s)
{
return s.size() >=5;
}
Thank you guys!
Firstly, your showList() has a potential problem with dereferencing
a null pointer. So it should look like this:
template <typename T>
void showList(const Node<T>* head)
{
while(head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
Secondly, it is more convenient to have auxiliary functions like
pushToList() and popFromList():
template <typename T>
void pushToList(Node<T>*& head, const T &element)
{
Node<T> *p = new Node<T>;
p->data = element;
p->next = head;
head = p;
}
template <typename T>
T popFromList(Node<T>*& head)
{
T value;
if (head != NULL) {
Node<T>* tmp = head;
value = head->data;
head = head->next;
delete tmp;
}
return value;
}
You can rewrite your arrayToList() using pushToList():
template <typename T>
Node<T>* arrayToList(const T tab[], size_t size)
{
Node<T>* head = NULL;
for(int i = size - 1; i >= 0; i--){
pushToList(head, tab[i]);
}
return head;
}
And implement deleteList() using popFromList():
template <typename T>
void deleteList(Node<T>*& head)
{
while (head != NULL) {
popFromList(head);
}
}
exctract() also can be implemented in terms of push and pop. You
just create two temporary lists and push to them according to the
predicate:
template<typename T>
Node<T>* extract(Node<T>*& head, bool (*predicate)(const T&))
{
Node<T> *extracted = NULL;
Node<T> *rest = NULL;
while (head != NULL) {
T value = popFromList(head);
if (predicate(value)) {
pushToList(extracted, value);
} else {
pushToList(rest, value);
}
}
reverseList(extracted);
reverseList(rest);
head = rest;
return extracted;
}
One problem is after the main work the temporary lists are
reversed. So we need the reverseList() function, which can be also
implemented in terms of push and pop:
template <typename T>
void reverseList(Node<T>*& head)
{
Node<T> *result = NULL;
while(head != NULL) {
pushToList(result, popFromList(head));
}
head = result;
}
It is not a very effective implementation but I think it does the work.
I've put the complete source code here.