Generic Single Linked List, No Viable overloaded = - c++

I am creating a generic single linked list for the first time. I have this error that states:
No viable overloaded '='
So I decided to overload the '=' operator to make it work but I am still receiving the same error and I am not sure why. Here is my header file:
#ifndef LinkedList_hpp
#define LinkedList_hpp
#include <iostream>
template<class T>
struct Node {
T data;
Node<T>* next;
};
template<class T>
class SingleLinkedList {
private:
Node<T>* head, tail;
SingleLinkedList & operator=(const SingleLinkedList &rhs) {
head = rhs.head;
tail = rhs.tail;
return *this;
}
public:
SingleLinkedList() {
head = nullptr;
tail = nullptr;
}
void createNode(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = nullptr;
if(head == nullptr) {
head = temp;
tail = temp;
temp = nullptr;
}
else {
tail->next = temp;
tail = temp;
}
}
void display() {
Node<T>* temp = new Node<T>;
temp = head;
while(temp != nullptr) {
std::cout << temp->data << "\t";
temp = temp->next;
}
}
void insert_start(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = head;
head = temp;
}
void insert_position(int pos, const T& theData) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
Node<T>* temp = new Node<T>;
temp = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
temp->data = theData;
previous->next = temp;
temp->next = current;
}
void delete_first() {
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
}
void delete_last() {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
while(current->next != nullptr) {
previous = current;
current = current->next;
}
tail = previous;
previous->next = nullptr;
delete current;
}
void delete_position(int pos) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
previous->next = current->next;
}
Node<T>* search(Node<T>* head, const T& target) {
}
};
Should I create an assignment operator in the struct Node? I am not sure what else to try.
Here is where I am getting an error:

Related

Linked List implementation of a Stack

Fairly new to implementing stacks and was looking for some possible feedback. My code gives the correct output, but I know this doesn't always mean it is working as it is suppose to. I chose to take the approach that implementing a stack using a linked list was essentially the same as your regular linked list implementation except that all the operations are done on the end of the list. I was not too sure if this approach was correct, but it followed the first in last out approach, and has the same complexity for access & search (O(n)) and insertion and deletion O(1). Such as pop() would just be deleting a node from the end of the linked list, and push() would just be appending a node to the end of the linked list. I have pasted my code below with comments within them explaining what I am doing or trying to do (if it is incorrect).
#include <iostream>
struct Node{
int data;
Node* next;
};
bool isEmpty(Node** stack){
if(*stack == NULL){
return true;
}
return false;
}
void push(Node** stack, int data){
Node* new_node = new Node();
new_node->data = data;
new_node->next=NULL;
// stack similar to "head"
if(isEmpty(&(*stack))){
*stack = new_node;
return;
}
Node* temp = *stack;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
void pop(Node** stack){
// checking if stack is empty
if(isEmpty(&(*stack))){
std::cout<<"Stack underflow"<<std::endl;
return;
}
Node* deleteMe = *stack;
// if at the first element in the stack
if(deleteMe->next == NULL){
*stack = (*stack)->next;
delete deleteMe;
return;
}
while(deleteMe->next != NULL){
if(deleteMe->next->next==NULL){
// saving the current location of the node before the node which I want to delete
Node* temp = deleteMe;
// updating the deleteMe pointer to the node which I want to delete
deleteMe = deleteMe->next;
// setting the current node before the deleteMe node to point to NULL instead of the node which I want to delete
temp->next = NULL;
delete deleteMe;
return;
}
deleteMe = deleteMe->next;
}
}
void printList(Node* stack){
Node* temp = stack;
while(temp!=NULL){
std::cout<<temp->data<<" ";
temp = temp->next;
}
std::cout<<"\n";
}
int top(Node** stack){
Node* top = *stack;
while(top->next!=NULL){
top = top->next;
}
return top->data;
}
int main(){
Node* stack = NULL;
// testing implementation below
push(&stack,10);
std::cout<<top(&stack)<<std::endl;
push(&stack,20);
std::cout<<top(&stack)<<std::endl;
push(&stack,30);
push(&stack,40);
printList(stack);
std::cout<<top(&stack)<<std::endl;
pop(&stack);
pop(&stack);
push(&stack,40);
std::cout<<top(&stack)<<std::endl;
}
Your implementation looks fine, one additional improvement can be done by maintaining head and tail pointer so that you can remove 1st and last element as needed. Here is example c++ code.
#include <iostream>
using namespace std;
template <class T> class node {
public:
node<T>() {}
~node<T>() {}
T data;
node<T> *next;
};
template <class T> class linked_list {
public:
linked_list<T>() : head(NULL), tail(NULL) {}
~linked_list<T>() {}
virtual void addFirst(T data) {
node<T> *n = new node<T>();
if (head == NULL)
tail = n;
n->data = data;
n->next = head;
head = n;
size++;
}
virtual void addLast(T data) {
node<T> *n = new node<T>();
n->data = data;
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
n->next = NULL;
tail = n;
}
virtual void reverse() {
if ((head == NULL) || (head->next == NULL))
return;
node<T> *current = head;
node<T> *previous = NULL;
node<T> *next = current->next;
tail = current;
while (current) {
next = current->next;
current->next = previous;
previous = current;
current = next;
}
head = previous;
}
virtual void print_nodes() {
node<T> *temp = head;
while (temp) {
cout << temp->data << " " << flush;
temp = temp->next;
}
cout << endl;
}
virtual void removeLast() {
node<T> *temp = head;
while (temp->next->next) {
temp = temp->next;
}
tail = temp;
delete temp->next;
temp->next = NULL;
}
virtual void removeFirst() {
node<T> *temp = head;
head = head->next;
delete temp;
}
private:
node<T> *head;
node<T> *tail;
uint32_t size;
};
int main(int argc, const char *argv[]) {
linked_list<uint32_t> *llist = new linked_list<uint32_t>();
llist->addLast(1);
llist->addFirst(5);
llist->addFirst(10);
llist->addFirst(15);
llist->addFirst(20);
llist->addLast(30);
llist->addFirst(40);
llist->print_nodes();
llist->reverse();
llist->print_nodes();
llist->removeLast();
llist->print_nodes();
llist->removeFirst();
llist->print_nodes();
return 0;
}

A normal Linked List

I decided to practice my linked-list knowledge, and decided to create one in C++!
I ran this code on two different online compilers - one worked, and the other is giving me a segfault. I cannot figure out what the problem is within my code, and am wondering if you can help me.
#include <iostream>
using namespace std;
struct Node {
int val;
Node *next;
Node(int val){
this->val = val;
this->next = NULL;
}
};
class LinkedList {
public:
Node *head;
void insertAtHead(Node *temp)
{
if (head == NULL)
{
head = temp;
}
else
{
temp->next = head;
head = temp;
}
}
void printList()
{
Node *temp = head;
while (temp != NULL)
{
cout << temp->val << endl;
temp = temp->next;
}
}
void insertAtBack(Node *temp)
{
if (head == NULL)
{
head = temp;
return;
}
Node *current = head;
while (current->next != NULL){
current = current->next;
}
current->next = temp;
}
void deleteNode(Node *temp)
{
if (head == NULL)
{
cout << "Empty List";
return;
}
if (head->val == temp->val)
{
head = head->next;
return;
}
Node *current = head;
while (current->next != NULL)
{
if (current->next->val == temp->val)
{
current->next = current->next->next;
return;
}
current = current->next;
}
}
};
int main()
{
Node *temp = new Node(10);
Node *temp2 = new Node(4);
Node *temp3 = new Node(17);
Node *temp4 = new Node(22);
Node *temp5 = new Node(1);
LinkedList x;
x.insertAtHead(temp);
x.insertAtHead(temp2);
x.insertAtBack(temp3);
// x.insertAtBack(temp4);
// x.insertAtBack(temp5);
// x.deleteNode(temp);
x.printList();
return 0;
}
The problem I am encountering is when I use the insertAtBack() method. It gives me a segfault, but I do not see what's wrong with the logic. It is pretty straight forward. The insertAtFront() method works, but once I call insertAtBack() my code fails.
make sure to initialize Node *head to NULL.
After insert temp(which is value 10), temp->next value becomes undefined value, because Node *head is undefined value.
Your LinkedList class is not initializing its head member. You need to add a constructor to initialize head to NULL.
Also, the class is leaking memory, as there is no destructor to free the nodes when a LinkedList instance is destroyed, and deleteNode() doesn't free the node being removed, either.
Try something more like this:
#include <iostream>
using namespace std;
struct Node
{
int val;
Node *next;
Node(int val) : val(val), next(NULL) { }
};
class LinkedList
{
private:
Node *head;
// if you are NOT using C++11 or later, add these
// until you are reading to tackle copy semantics!
/*
LinkedList(const LinkedList &);
LinkedList& operator=(const LinkedList &);
*/
public:
LinkedList() : head(NULL) {} // <-- add this!
~LinkedList() // <-- add this!
{
Node *current = head;
while (current)
{
Node *next = current->next;
delete current;
current = next;
}
}
void insertAtHead(Node *temp)
{
if (!head)
{
head = temp;
}
else
{
temp->next = head;
head = temp;
}
}
void printList()
{
Node *current = head;
while (current)
{
cout << current->val << endl;
current = current->next;
}
}
void insertAtBack(Node *temp)
{
if (!head)
{
head = temp;
return;
}
Node *current = head;
while (current->next) {
current = current->next;
}
current->next = temp;
}
void deleteNode(Node *temp)
{
if (!head)
{
cout << "Empty List";
return;
}
if (head == temp)
{
head = temp->next;
delete temp;
return;
}
Node *current = head;
while (current->next)
{
if (current->next == temp)
{
current->next = temp->next;
delete temp;
return;
}
current = current->next;
}
}
// if you ARE using C++11 or later, add these until
// you are reading to tackle copy and move semantics!
/*
LinkedList(const LinkedList &) = delete;
LinkedList(LinkedList &&) = delete;
LinkedList& operator=(const LinkedList &) = delete;
LinkedList& operator=(LinkedList &&) = delete;
*/
};
int main()
{
Node *temp = new Node(10);
Node *temp2 = new Node(4);
Node *temp3 = new Node(17);
Node *temp4 = new Node(22);
Node *temp5 = new Node(1);
LinkedList x;
x.insertAtHead(temp);
x.insertAtHead(temp2);
x.insertAtBack(temp3);
// x.insertAtBack(temp4);
// x.insertAtBack(temp5);
// x.deleteNode(temp);
x.printList();
return 0;
}
Which can then be simplified further:
#include <iostream>
using namespace std;
struct Node
{
int val;
Node *next;
Node(int val, Node *next = NULL) : val(val), next(next) { }
};
class LinkedList
{
private:
Node *head;
// if you are NOT using C++11 or later, add these
// until you are reading to tackle copy semantics!
/*
LinkedList(const LinkedList &);
LinkedList& operator=(const LinkedList &);
*/
public:
LinkedList() : head(NULL) {} // <-- add this!
~LinkedList() // <-- add this!
{
Node *current = head;
while (current)
{
Node *next = current->next;
delete current;
current = next;
}
}
Node* insertAtHead(int value)
{
Node *temp = new Node(value, head);
if (!head)
head = temp;
return temp;
}
void printList()
{
Node *current = head;
while (current)
{
cout << current->val << endl;
current = current->next;
}
}
Node* insertAtBack(int value)
{
Node **current = &head;
while (*current)
current = &((*current)->next);
*current = new Node(value);
return *current;
}
/*
void deleteNode(Node *temp)
{
Node *current = head, *previous = NULL;
while (current)
{
if (current == temp)
{
if (previous)
previous->next = temp->next;
if (head == temp)
head = temp->next;
delete temp;
return true;
}
previous = current;
current = current->next;
}
cout << "Not found" << endl;
return false;
}
*/
bool deleteValue(int value)
{
Node *current = head, *previous = NULL;
while (current)
{
if (current->val == value)
{
if (previous)
previous->next = temp->next;
if (head == temp)
head = temp->next;
delete temp;
return true;
}
previous = current;
current = current->next;
}
cout << "Not found" << endl;
return false;
}
// if you ARE using C++11 or later, add these until
// you are reading to tackle copy and move semantics!
/*
LinkedList(const LinkedList &) = delete;
LinkedList(LinkedList &&) = delete;
LinkedList& operator=(const LinkedList &) = delete;
LinkedList& operator=(LinkedList &&) = delete;
*/
};
int main()
{
LinkedList x;
x.insertAtHead(10);
x.insertAtHead(4);
x.insertAtBack(17);
// x.insertAtBack(22);
// x.insertAtBack(1);
// x.deleteValue(10);
x.printList();
return 0;
}

Attempting to build a generic single linked list for the first time, getting undefined symbols error

As the title suggests, I am trying to learn data structures and I am starting with a linked list. I decided to make it generic since I thought it would be useful to do to handle other data types.
I am getting these associated errors:
I am not sure what I am doing wrong and I cannot identify the error. Here is my code starting with the header file:
#ifndef LinkedList_hpp
#define LinkedList_hpp
template<class T>
struct Node {
T data;
Node<T>* next;
};
template<class T>
class SingleLinkedList {
private:
Node<T>* head, tail;
public:
SingleLinkedList();
void createNode(const T& theData);
void display();
void insert_start(const T& theData);
void insert_position(int pos, const T& theData);
void delete_first();
void delete_last();
void delete_position(int pos);
Node<T>* search(Node<T>* head, const T& target);
};
#endif /* LinkedList_hpp */
Now here is the associated .cpp file:
#include "LinkedList.hpp"
#include <iostream>
template<class T>
SingleLinkedList<T>::SingleLinkedList() {
head = nullptr;
tail = nullptr;
}
template<class T>
void SingleLinkedList<T>::createNode(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = nullptr;
if(head == nullptr) {
head = temp;
tail = temp;
temp = nullptr;
}
else {
tail->next = temp;
tail = temp;
}
}
template<class T>
void SingleLinkedList<T>::display() {
Node<T>* temp = new Node<T>;
temp = head;
while(temp != nullptr) {
std::cout << temp->data << "\t";
temp = temp->next;
}
}
template<class T>
void SingleLinkedList<T>::insert_start(const T& theData) {
Node<T>* temp = new Node<T>;
temp->data = theData;
temp->next = head;
head = temp;
}
template<class T>
void SingleLinkedList<T>::insert_position(int pos, const T &theData) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
Node<T>* temp = new Node<T>;
temp = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
temp->data = theData;
previous->next = temp;
temp->next = current;
}
template<class T>
void SingleLinkedList<T>::delete_first() {
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
}
template<class T>
void SingleLinkedList<T>::delete_last() {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
while(current->next != nullptr) {
previous = current;
current = current->next;
}
tail = previous;
previous->next = nullptr;
delete current;
}
template<class T>
void SingleLinkedList<T>::delete_position(int pos) {
Node<T>* previous = new Node<T>;
Node<T>* current = new Node<T>;
current = head;
for(int i = 1; i < pos; i++) {
previous = current;
current = current->next;
}
previous->next = current->next;
}
And finally here is the main.cpp file where I attempt to test the code:
#include <iostream>
#include "LinkedList.hpp"
int main(int argc, const char * argv[]) {
SingleLinkedList<int> obj;
obj.createNode(2);
obj.createNode(4);
obj.createNode(6);
obj.createNode(8);
obj.display();
return 0;
}
You need to put the implementation of your member functions into the header file.

changing linked list into a doubly linked list

Hi could you please help me change this linked list into a doubly linked list ?
I would be very grateful for help :)
#include <iostream>
using namespace std;
template <class T>
struct node
{
T data;
node<T> *next;
node<T> *prev;
};
template <class T>
class Container
{
public:
//constructs a new empty Kontener
Container()
{
head = new node<T>;
head->next = head;
head->prev = head;
};
//constructs a new jp_list that is a copy of an existing list
Container(const Container<T>& rt_side)
{
head = new node<T>;
head->next = head;
head->prev = head;
node<T> *crt_ptr = rt_side.head->next;
while(crt_ptr != rt_side.head)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
};
//adds a data node to the front of the list
void push_front(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
temp->next = head->next;
head->next->prev = temp;
temp->prev = head;
head->next = temp;
};
//adds a data node to the end of the list
void push_back(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
head->prev->next = temp;
temp->prev = head->prev;
temp->next = head;
head->prev = temp;
};
//removes the first node and returns the data
T pop_front()
{
node<T> *temp = head->next;
T temp_data = head->next->data;
head->next = temp->next;
temp->next->prev = head;
delete temp;
return temp_data;
};
//removes the last node and returns the data
T pop_back()
{
node<T> *temp = head->prev;
T temp_data = head->prev->data;
head->prev = temp->prev;
temp->prev->next = head;
delete temp;
return temp_data;
};
//resturns the size of the list
int size()
{
int size = 0;
node<T> *crt_ptr; //pointer to current node
crt_ptr = head->next;
while(crt_ptr != head)
{
size += 1;
crt_ptr = crt_ptr->next; //advance to the next node then loop
}
return size;
};
//prints out all the data in the list
void display_all()
{
node<T> *crt_ptr = head->next;
for(int i = 0; crt_ptr != head; i++)
{
cout << "Node " << (i+1) << ": " << crt_ptr->data << endl;
crt_ptr = crt_ptr->next;
}
};
Container& operator= (const Container& rt_side)
{
if(this == &rt_side)
return *this;
node<T> *crt_ptr = head->next;
//empty this list so the rt_side can be coppied in
while(crt_ptr != head)
{
crt_ptr = crt_ptr->next;
pop_front();
}
crt_ptr = rt_side.head->next;
while(crt_ptr != rt_side.head)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
return *this;
};
virtual ~Container()
{
int list_size = size();
for(int i = 0; i < list_size; i++)
{
pop_front();
}
delete head;
};
private:
node<T> *head;
};
#endif
I am just a beginner so please help me :)
The tail would always point to the last item that was inserted into the list.
However, I do not think that having a tail pointer makes it necessarily a doubly linked list. A singly linked list can also have a tail pointer (however useless it might be). I believe you are asking to create a double ended doubly linked list.
You already have the next and previous pointers to enable the double link. All you have to do, is when you push something into the list, you need to make the tail pointer point to the node that is being added. Similarly, when removing a node, you need the tail pointer to point to tail's previous BEFORE deleting the last node.
* UPDATE *
Here is some code. I am assuming a double ended doubly linked list with two ends.
void push_front(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else if(head == tail)
{
head->next = temp;
temp->prev = head;
tail = temp;
}
else
{
temp->next = head->next;
head->next->prev = temp;
temp->prev = head;
head->next = temp;
}
};
//adds a data node to the end of the list
void push_back(T nw_data)
{
node<T> *temp = new node<T>;
temp->data = nw_data;
if(head == nullptr)
{
head = temp;
tail = temp;
}
else if(head == tail)
{
head->next = temp;
temp->prev = head;
tail = temp;
}
else
{
temp->prev = tail;
tail->next = temp;
tail = temp;
}
};
T pop_back()
{
node<T> *temp = tail;
T temp_data = tail->data;
tail = tail->prev;
tail->next = null;
delete temp;
return temp_data;
};
* UPDATE * Copy Constructor
In your copy constructor, if the push_back sets the tail, then all you need to do is to push_back the nodes like you are doing. head->next = head and head->prev = head makes the linked list cyclical.
Container(const Container<T>& rt_side)
{
this->head = rt_side.head;
node<T> * crt_ptr = rt_side.head->next;
while (crt_ptr != null)
{
push_back(crt_ptr->data);
crt_ptr = crt_ptr->next;
}
};

C++ Why does my Linked List template class fail when I create an object of a class that has a linked list in it?

I wrote this LinkedList template class, which isn't finished yet- I have yet to add safety features and more methods. As of now it does what I need it to. But it fails in a certain situation and I don't know why.
template<class data_type> class LinkedList {
private:
struct Node {
data_type data;
Node* prev;
Node* next;
Node() : prev(NULL), next(NULL) {}
};
Node* head;
Node* GetLastNode() {
Node* cur = head;
while (cur->next != NULL)
cur = cur->next;
return cur;
}
public:
LinkedList() {
head = new Node;
head->prev = head;
head->next = NULL;
}
LinkedList(LinkedList<data_type> &to_copy) {
head = new Node;
head->prev = head;
head->next = NULL;
for (int i = 1; i <= to_copy.NumberOfItems(); i++) {
this->AddToList(to_copy.GetItem(i));
}
}
~LinkedList() {
DeleteAll();
delete head;
head = NULL;
}
void AddToList(const data_type data) {
Node* last = GetLastNode();
Node* newnode = last->next = new Node;
newnode->prev = last;
newnode->data = data;
}
void Delete(const unsigned int position) {
int currentnumberofitems = NumberOfItems();
Node* cur = head->next;
int pos = 1;
while (pos < position) {
cur = cur->next;
pos++;
}
cur->prev->next = cur->next;
if (position != currentnumberofitems)
cur->next->prev = cur->prev;
delete cur;
}
void DeleteAll() {
Node* last = GetLastNode();
Node* prev = last->prev;
while (prev != head) {
delete last;
last = prev;
prev = last->prev;
}
head->next = NULL;
}
data_type GetItem(unsigned int item_number) {
Node* cur = head->next;
for (int i = 1; i < item_number; i++) {
cur = cur->next;
}
return cur->data;
}
data_type* GetItemRef(unsigned int item_number) {
Node* cur = head->next;
for (int i = 1; i < item_number; i++) {
cur = cur->next;
}
return &(cur->data);
}
int NumberOfItems() {
int count(0);
Node* cur = head;
while (cur->next != NULL) {
cur = cur->next;
count++;
}
return count;
}
};
I stated my problem in the question and here is an example:
class theclass {
public:
LinkedList<int> listinclass;
};
void main() {
LinkedList<theclass> listoftheclass;
theclass oneclass;
oneclass.listinclass.AddToList(5);
listoftheclass.AddToList(oneclass);
cout << listoftheclass.GetItem(1).listinclass.GetItem(1);
}
I can't figure out why it doesn't run right.
You need to implement an assignment operator. The problem starts in this function here:
void AddToList(const data_type data) {
Node* last = GetLastNode();
Node* newnode = last->next = new Node;
newnode->prev = last;
newnode->data = data; <---------------------------- Right there
}
Since data_type is your class, and you don't have an appropriate assignment operator, you are just getting a member by member(shallow) copy there.
See The Rule of Three
You should also probably implement a swap function, and have your assignment operator use that.
See Copy and Swap Idiom
In C++03, local classes can't be template arguments. Move theclass outside of main, and it will work.
In C++0x this limitation is removed.