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
Related
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
I am having some trouble making the appropriate changes from a post I made on code review. Here is the original post I made here. Specifically, I am at the point where I am revising my insertPosition function.
Previously my function was like this:
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T& theData) {
Node* prev = new Node;
Node* current = head;
Node* newNode = new Node;
for(int i = 1; i < pos; i++) {
prev = current;
current = current->next;
}
newNode->data = theData;
prev->next = newNode;
newNode->next = current;
}
But now, from what I have been told to do was make it more like this:
Node* cur_node = head;
int i = 0;
while (cur_node) {
if (i++ == pos) {
// do the deed
}
cur_node = cur_node->next;
}
I am not sure what to write in the // do the deed part. What I have tried is this:
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T& theData) {
Node* current = head;
int i = 0;
while(current) {
if(i++ == pos) {
Node* newNode = new Node;
newNode->data = theData;
newNode->next = newNode->previous;
}
current = current->next;
}
}
But I do not get the code to work at all when I test it out. There are also various other things I need to change I am sure but I would like to get a second opinion of my code I have thus far.
Here is the header file:
#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 createNode(const T& theData);
void createNode(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) {
createNode(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>
DoubleLinkedLists<T>& DoubleLinkedLists<T>::operator=(DoubleLinkedLists const& rhs) {
DoubleLinkedLists copy(rhs);
swap(copy);
return *this;
}
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>::createNode(const T& theData) {
Node* newData = new Node;
newData->data = theData;
newData->next = nullptr;
if(head == nullptr) {
newData->previous = nullptr;
head = newData;
tail = newData;
}
else {
newData->previous = tail;
tail->next = newData;
tail = newData;
}
}
template <class T>
void DoubleLinkedLists<T>::createNode(T&& theData) {
Node* newData = new Node;
newData->data = std::move(theData);
newData->next = nullptr;
if(head == nullptr) {
newData->previous = nullptr;
head = newData;
tail = newData;
}
else {
newData->previous = tail;
tail->next = newData;
tail = newData;
}
}
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) {
// Node* prev = new Node;
// Node* current = head;
// Node* newNode = new Node;
//
// for(int i = 1; i < pos; i++) {
// prev = current;
// current = current->next;
// }
// newNode->data = theData;
// prev->next = newNode;
// newNode->next = current;
//}
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T& theData) {
Node* current = head;
int i = 0;
while(current) {
if(i++ == pos) {
Node* newNode = new Node;
newNode->data = theData;
newNode->next = newNode->previous;
}
current = current->next;
}
}
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>::deleteHead() {
Node* old = head;
head = head->next;
delete old;
}
template <class T>
void DoubleLinkedLists<T>::deleteTail() {
Node* prev = nullptr;
Node* current = head;
while(current->next != nullptr) {
prev = current;
current = current->next;
}
tail = prev;
prev->next = nullptr;
delete current;
}
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;
}
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 */
Here is the main.cpp file to test the above implementation:
#include <iostream>
#include "DoubleLinkedLists.h"
int main(int argc, const char * argv[]) {
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Double Linked List //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
DoubleLinkedLists<int> obj;
obj.createNode(2);
obj.createNode(4);
obj.createNode(6);
obj.createNode(8);
obj.createNode(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(4);
std::cout << obj << std::endl;
std::cout << std::endl;
obj.search(8) ? printf("Yes"):printf("No");
return 0;
}
Update:
This is what I have done so far, I am pass in the data into a new node and then link previous node with the next node. Although, the code runs but nothing actually gets inserted into a position so I believe it does not even go through the while loop. I am not sure what the problem is.
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T& theData) {
Node* current = head;
int i = 0;
while(current) {
if(i++ == pos) {
Node* newNode = new Node;
newNode->data = theData;
newNode->previous = newNode->next;
}
current = current->next;
}
}
So...
template <class T>
void DoubleLinkedLists<T>::insertPosition(int pos, const T& theData) {
Node* current = head;
int i = 0;
while (current != nullptr) {
if (i++ == pos) {
Node* newNode = new Node;
newNode->data = theData;
// Let's do the wiring
newNode->previous = current->previous;
newNode->next = current;
if (newNode->previous != nullptr) { // If the node is inserted at the end
newNode->previous->next = newNode;
}
current->previous = newNode;
return;
}
current = current->next;
}
}
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
}
}
so I have an assignment where I need to create a doubly linked list and then create a stack and queue class and inherit from the linkedlist class in order to create an RPN calculator. So far I have created my doubly linkedlist class and the other to classes. However, I am having trouble understanding how I will inherit and use the linked list class with the stack and queue. I will provide what I have so far.
I have gone to tutoring and have not had much help so I thought I would look for some extra help, do not want homework done for me but to just be pointed in the right direction.
Stack.h
using std::iterator;
using std::vector;
using std::string;
template<class T>
class Stack : public vector<T>
{
private:
T getElement(bool erase);
typename std::vector<T> ::iterator pEnd;
T top;
public:
Stack();
T pop();
T peek();
void push(T elem);
};
template<class T>
Stack<T>::Stack()
{
}
template<class T>
void Stack<T>::push(T elem)
{
this->push_back(elem);
}
template<class T>
T Stack<T>::peek()
{
return this->getElement(false);
}
template<class T>
T Stack<T>::pop()
{
return this->getElement(true);
}
template<class T>
T Stack<T>::getElement(bool erase)
{
this->pEnd = this->end() - 1;
T tmp;
if (this->size() > 0)
{
tmp = *this->pEnd;
if (erase) {
this->erase(pEnd);
}
}
return tmp;
}
Queue.h
using namespace std;
class Queue
{
private:
int items[MAXQUEUE];
int head;
int tail;
public:
Queue();
bool isEmpty();
bool isFull();
bool enqueue(int item);
int dequeue();
int peek();
};
Queue::Queue()
:head(QEMPTY), tail(QEMPTY)
{
}
bool Queue::isEmpty()
{
return this->head == this->tail;
}
bool Queue::isFull()
{
return this->tail == MAXQUEUE;
}
bool Queue::enqueue(int item)
{
if (this->isFull())
return false;
this->items[this->tail] = item;
tail = (tail + 1) % MAXQUEUE;
return true;
}
int Queue::dequeue()
{
if (this->isEmpty())
return EMPTY;
int item = this->items[head];
this->head = (this->head + 1) % MAXQUEUE;
return item;
}
int Queue::peek() {
return this->tail;
}
doublylinkedlist.h
using std::iterator;
using std::vector;
using std::string;
/*START OF NODE CLASS*/
/*---------------------------------------------*/
template<class T>
struct Node
{
T Data;
T Search;
T value;
Node<T>*Next;
Node<T>*Prev;
};
template<class T>
class LinkedList
{
private:
Node<T> *Head;
public:
LinkedList();
void addNode(T Data);
void deleteNode(T Search);
void insert(T Search, T value);
void printListBackwards();
void printListForwards();
};
template<class T>
LinkedList<T>::LinkedList()
{
this->Head = NULL;
}
template<class T>
void LinkedList<T>::addNode(T data)
{
if (Head == NULL)
{
Head = new Node<T>;
Head->Data = data;
Head->Next = NULL;
Head->Prev = NULL;
}
else
{
Node<T>*p = this->Head;
while (p->Next != NULL)
p = p->Next;
Node<T>*n = new Node<T>;
n->Data = data;
n->Next = NULL;
p->Next = n;
n->Prev = p;
}
}
template<class T>
void LinkedList<T>::insert(T Search, T value)
{
Node *p = Head;
while (p->Data != Search)
{
p = p->Next;
}
Node *n = new Node;
n->Data = value;
n->Next = p->Next;
p->Next = n;
}
template<class T>
void LinkedList<T>::deleteNode(T Search)
{
Node *p = Head;
while (p->Next->Data != Search)
{
p = p->Next;
}
Node *delPtr = p->Next;
p->Next = p->Next->Next;
delete delPtr;
}
template<class T>
void LinkedList<T>::printListBackwards()
{
Node<T> *p = Head;
while (p->Next != NULL)
{
p = p->Next;
}
while (p != NULL)
{
cout << p->Data<< endl;
p = p->Prev;
}
}
template<class T>
void LinkedList<T>::printListForwards()
{
Node<T> *p = Head;
while (p != NULL)
{
cout << p->Data << endl;
p = p->Next;
}
}
A doubly linked list can be added to at the head or the tail, and removed at the tail.
A stack pushes at one end (the head?) and pops at the same end (the head).
A queue pushes at one end (the tail) and pops at the other end (the head).
I've gone through a bunch of threads trying to understand what is going on exactly with linked lists and bubblesort, and I think I get the bulk of it.
Right now my program is simply crashing when I get to the sort function and I am not sure why. Hopefully another set of eyes will see what I do not.
Any help is greatly appreciated.
DoublyList.h:
#include "listNode.h"
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
template <typename T>
class DoublyList
{
public:
DoublyList();
~DoublyList();
void addFront(T d);
void addBack(T d);
T removeFront();
T removeBack();
T peak();
bool isEmpty();
int getSize();
void printList();
void sortList();
private:
ListNode<T> *front;
ListNode<T> *back;
int numOfElements;
};
template <typename T>
DoublyList<T>::DoublyList(){
front = NULL;
back = NULL;
numOfElements = 0;
}
template <typename T>
DoublyList<T>::~DoublyList(){
if(numOfElements!=0){
ListNode<T> *current;
current = front;
while (current != back)
{
ListNode<T> *temp = current;
current = current->next;
temp->next = NULL;
temp->prev = NULL;
delete temp;
numOfElements--;
}
//at this point current = back, now delete it
current->next = NULL;
current->prev = NULL;
delete current;
numOfElements--;
}
//this is a safeguard if you create a LL and then delete it without doing anything to it
else{
cout<<"deleted empty LL"<<endl;
delete front;
delete back;
}
}
template <typename T>
void DoublyList<T>::addFront(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
back = node;
}
else{
front->prev = node;
}
node->next = front;
front = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeFront()
{
if (isEmpty()){
return T();
}
else
{
ListNode<T>* temp = front;
if (front->next == 0){
back = 0;
}
else
{
front->next->prev = 0;
}
front = front->next;
temp->next = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
void DoublyList<T>::addBack(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
front = node;
}
else{
back->next = node;
}
node->prev = back;
back = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeBack()
{
if (isEmpty()) {
return T();
}
else
{
ListNode<T>* temp;
temp = back;
if (back->prev == 0){
front = 0;
}
else{
back->prev->next = 0;
}
back = back->prev;
temp->prev = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
T DoublyList<T>::peak()
{
if (isEmpty()) {
return T();
}
return front->data;
}
template <typename T>
int DoublyList<T>::getSize(){
return numOfElements;
}
template <typename T>
bool DoublyList<T>::isEmpty(){
if(numOfElements == 0){
return true;
}
else{
return false;
}
}
template <typename T>
void DoublyList<T>::printList(){
if(numOfElements!=0){
ListNode<T> *current = front;
while(current!=back)
{
cout<<current->data<<endl;
current = current->next;
}
cout<<back->data<<endl;
}
else{
cout<<"list is empty"<<endl;
}
}
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current;
ListNode<T> *dummy;
ListNode<T> *next;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current -> next != NULL){
if(current-> data < current -> next -> data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy -> data = current -> data;
current -> data = current -> next -> data;
current -> next -> data = dummy -> data;
}
current = current -> next;
}
}
}
#endif
listNode.h:
#include <iostream>
#ifndef LISTNODE_H
#define LISTNODE_H
using namespace std;
template <typename T>
class ListNode
{
public:
T data;//the data that we will store
ListNode();
ListNode(int d);
~ListNode();
ListNode *next;//int and ptr and the member variables
ListNode *prev;
};
template <typename T>
ListNode<T>::ListNode(int d){
data = d;
next = NULL;
prev = NULL;
}
template <typename T>
ListNode<T>::ListNode(){}
template <typename T>
ListNode<T>::~ListNode(){
delete next;
delete prev;
cout<<"deleted Node"<<endl;
}
#endif
testList.cpp
#include <iostream>
#include "doublyList.h"
#include "genericQueue.h"
int main(){
DoublyList<int> testQueue;
testQueue.addBack(3);
testQueue.addBack(5);
testQueue.addBack(2);
testQueue.addBack(10);
testQueue.addBack(1);
cout << "Before Sort: " << endl;
testQueue.printList();
cout << "After Sort: " << endl;
testQueue.sortList();
testQueue.printList();
}
The erors I could find so far are:
Your default ListNode() constructor doesn't null the next and prev pointers.
In void DoublyList<T>::sortList() you don't initialize dummy, so it just points into nowhere. Actually there is no reason to use a node list at all, you can just directly use a variable of type T.
You don't initialize current in the same function and you actually should reset current to e.g. front at the beginning of each outer loop.
You don't use next at all (and don't need to), so just remove it.
To sum it up, this is what void DoublyList<T>::sortList() could look like:
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current=front;
T dummy;
if (current == NULL) return;
if (current->next == NULL) return;
int swapped = 1;
while (swapped){
current = front;
swapped = 0; //last pass unless there is a swap
while (current->next != NULL){
if (current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy = current->data;
current->data = current->next->data;
current->next->data = dummy;
}
current = current->next;
}
}
}
and this is my suggestion for the ListNode constructor.
template <typename T>
ListNode<T>::ListNode() :
next(nullptr),
prev(nullptr),
data{}
{}
Besides that, I also agree with DaveB that swapping pointers is the approach you should actually use.
To start with you need to initialize current in your sort function,
current = first;
template <typename T>
void DoublyList<T>::sortList(){
ListNode<T> *current;
ListNode<T> *next;
T tmp;
current = front;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current->next != nullptr){
if(current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
tmp = current->data;
current->data = current->next->data;
current->next->data = tmp;
}
current = current -> next;
}
if (swapped) // go back to start of list for next pass
current = front;
}
}