c++ single linked list segmentation fault t - c++

I am trying to write a code making a single linked list. I want to put all my array elements into each node and link them. But when I run my code I keep getting the segmentation fault error. I do not get why I am getting this error.
Can anybody help?? Thanks!!
linked_list_main.cc
#include <iostream>
#include "linked_list.h"
int main() {
int array[5];
List<int> list(array, 5);
std::cout << list;
return 0;
}
template <class T>
class Node {
public:
T data;
Node<T>* next;
};
This is my linked_list.h file.
class List {
private:
Node<T> *head;
public:
List() : head(NULL) {};
~List() {
Node<T>* ptr;
for(ptr = head; ptr == NULL; ptr = head->next)
delete ptr;
}
List(T* arr, int n_nodes){
Node<T>* tmp = head;
for(int i = 0; i < n_nodes; i++ ) {
Node<T>* node = new Node<T>;
node->data = arr[i];
if(tmp != NULL) {
node->next = tmp;
tmp = node;
}
}
}
friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {
Node<T>* cur = rhs.head;
while(cur != NULL) {
if(cur->next == NULL)
out << cur->data << " ";
else
out << cur->data << ", ";
cur = cur->next;
}
}
};

You need to change this
List(T* arr, int n_nodes){
Node<T>* tmp = head;
...
}
to this
List(T* arr, int n_nodes){
Node<T>* tmp = NULL;
...
head = tmp;
}
Pointers are tricky, learn to use a debugger. Will be the best hour you've ever spent when learning how to program.

Related

Linked List insertion isn't working in for/while loop

I am learning DSA, and was trying to implement linked list but the insertion function that i wrote is not
working in a for or while loop, its not the same when i call that function outside the loop, it works that way. I am not able to figure it out, please someone help me.
#include <iostream>
class Node {
public:
int data;
Node *next;
Node(int &num) {
this->data = num;
next = NULL;
}
};
class LinkedList {
Node *head = NULL;
public:
void insert(int num) {
Node *tmp;
if (head == NULL) {
head = new Node(num);
tmp = head;
} else {
tmp->next = new Node(num);
tmp = tmp->next;
}
}
void printList() {
Node *tmp = head;
while (tmp) {
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList() {
Node *curr = head, *prev = NULL, *nextNode;
while (curr) {
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main() {
LinkedList list1;
// This is not working
int num;
while (num != -1) {
std::cin >> num;
list1.insert(num);
}
// This is working
// list1.insert(1);
// list1.insert(2);
// list1.insert(3);
// list1.insert(4);
// list1.insert(5);
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}
I expect this after insertion
Edit:
although #Roberto Montalti solved this for me, but before that I tried passing incrementing value using a for loop which worked but as soon as I pull that cin out it crashes. can someone tell me what's happening under the hood?
for (int i = 1; i <= 10; i++)
{
list1.insert(i);
}
When inserting the nth item (1st excluded) tmp is a null pointer, i don't understand what you are doing there, you are assigning to next of some memory then you make that pointer point to another location, losing the pointer next you assigned before, you must keep track of the last item if you want optimal insertion. This way you are only assigning to some *tmp then going out of scope loses all your data... The best way is to just keep a pointer to the last inserted item, no need to use *tmp.
class LinkedList
{
Node *head = NULL;
Node *tail = NULL;
public:
void insert(int num)
{
if (head == NULL)
{
head = new Node(num);
tail = head;
}
else
{
tail->next = new Node(num);
tail = tail->next;
}
}
...
}
You need to loop until you reach the end of the list and then add the new node after that. Like this.
void insert(int num) {
Node *tmp = head;
if (head == NULL) {
head = new Node(num);
}
else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = new Node(num);
}
}
first of all you need to define a node for each of the tail and head of the list as follows
Node *h;
Node *t;
you may also separate the Node from the LinkedList class so you can modify easily
class Node{
public:
int data;
Node *next;
Node(int data, Node* next);
~Node();
};
Node::Node(int data, Node* next)
{
this->data= data;
this->next= next;
}
Node::~Node(){}
}
after that you can try to add these functions to your LinkedList class
so it can deal with other special cases such empty list or full, etc..
void addToHead(int data){
Node *x = new Node(data,h);
h=x;
if(t==NULL){
t=x;
}
void addToTail(int data){
Node *x = new Node(data,NULL);
if(isEmpty()){
h=t=x;
}
else
{
t->next=x;
t=x;
}
}
now for the insert function try this after you implemented the Node class and the other functions,
void insert(int v){
if(h==nullptr){addToHead(v); return;}
if(h->data>=v) {addToHead(v);return;}
if(t->data<=v) {addToTail(v); return;}
// In this case there is at least two nodes
Node *k=h->next;
Node *p=h;
while(k != nullptr){
if(k->data >v){
Node *z =new Node(v,k);
p->next=z;
return;
}
p=k;
k=k->next;
}
}
the idea of making all of this is not lose the pointer when it goes through elements in the Linked List so you don't end up with a run time error.
I hope this can be useful to you.
There was an issue with your insert function.
Read about segmentation fault here https://www.geeksforgeeks.org/core-dump-segmentation-fault-c-cpp/#:~:text=Core%20Dump%2FSegmentation%20fault%20is,is%20known%20as%20core%20dump.
for a quick workaround you can use this
using namespace std;
#include <iostream>
class Node
{
public:
int data;
Node *next;
Node(int num)
{
this->data = num;
next = NULL;
}
};
class LinkedList
{
Node *head = NULL;
public:
void insert(int num)
{
Node *tmp= new Node(num);
tmp->next=head;
head=tmp;
}
void printList()
{
Node *tmp = head;
while (tmp)
{
std::cout << tmp->data << " ";
tmp = tmp->next;
}
std::cout << std::endl;
}
void reverseList()
{
Node *curr = head, *prev = NULL, *nextNode;
while (curr)
{
nextNode = curr->next;
curr->next = prev;
prev = curr;
curr = nextNode;
}
head = prev;
}
};
int main()
{
LinkedList list1;
// This is not working
int num,i=0,n;
cout<<"Type the value of n";
cin>>n;
while (i<n)
{
cin >> num;
cout<<num<<" "<<&num<<endl;
list1.insert(num);
i++;
}
list1.printList();
list1.reverseList();
list1.printList();
return 0;
}

How to get below linked list with friend operator to working?

I am trying to execute linked list with the below code.But I am unable to figure out the mistake in it.
I got the concept of it but I am failing to implement the same.
Any help is highly appreciated.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next;
Node(int j) : data(j), next(nullptr) {}
friend ostream &operator<<(ostream &os, const Node &n) {
cout << "Node\n"
<< "\tdata: " << n.data << "\n";
return os;
}
};
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp->next=nullptr;
Node *cur = *head;
while(cur) {
if(cur->next == nullptr) {
cur->next = temp;
return;
}
cur = cur->next;
}
};
void printList(const Node *head){
const Node *list = head;
while(list) {
cout << list;
list = list->next;
}
cout << endl;
cout << endl;
};
void deleteList(Node *head){
Node *delNode =nullptr;
while(head) {
delNode = head;
head = delNode->next;
delete delNode;
}};
int main() {
Node *list = nullptr;
addElement(&list, 1);
addElement(&list, 2);
printList(list);
deleteList(list);
return 0;
}
after compiling I am getting no error and no output.So I am unable to figure what is going wrong or else my implementation of which is not right!
Here an error straightaway
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp is null, but you dereference it. It's an error to dereference a null pointer.
I guess you meant this
void addElement(Node **head, int data) {
Node *temp = new Node(data);
which allocates a new Node, initialises it with data and makes temp point to the newly allocated Node.

singly linked list c++ constructor, destructor and printing out

I am a beginner learning c++, and currently making a singly linked list. I have faced some problems and I thought for a very long time, searched a lot but still do not have an answer for this code so I am begging for some help..
So this is my linked.h
template <class T>
class Node {
public:
T data;
Node<T>* next;
};
template <class T>
class List {
private:
Node<T> *head;
public:
List() : head(NULL) {};
~List() {
Node<T>* ptr, tmp;
for(ptr = head->next; ptr == NULL; ptr = head->next) {
delete ptr;
}
}
List(T* arr, int n_nodes) {
head = NULL;
Node<T> *tmp = head;
for(int i = 0; i < n_nodes; i++) {
Node<T>* node = new Node<T>;
node->data = arr[i];
if(head == NULL) {
head->next = node;
tmp = node;
}
else {
tmp->next = node;
node->next = NULL;
tmp = node;
}
}
}
friend std::ostream& operator<<(std::ostream& out, List<T>& rhs) {
Node<T>* cur = rhs.head;
out << cur;
while(cur != NULL) {
if(cur->next != NULL) {
out << cur->data << ", ";
cur = cur->next;
}
else
out << cur->data << " ";
}
return out;
}
};
and this is my main.cc file.
#include <iostream>
#include "linked.h"
int main() {
int array[5] = {12, 7, 9, 21, 13};
List<int> li(array, 5);
std::cout << li;
return 0;
}
I keep on getting segmentation fault when running the constructor and I don't get why. Where am I making a mistake? Any help would be appreciated!
You could cover the issue with a pointer to pointer:
List(T* arr, int n_nodes)
{
Node<T>** tmp = &head; // tmp *pointing* to uninitialized(!) head pointer
for(int i = 0; i < n_nodes; i++)
{
Node<T>* node = new Node<T>();
node->data = arr[i];
// now the trick:
*tmp = node; // !!!
// you now have assigned the new node to whatever pointer
// the tmp pointer points to - which initially is - guess - head...
// but we now need to advance!
tmp = &node->next;
}
// tmp now points to latestly created node's next pointer
// (or still head, if no nodes where created because of n_nodes == 0)
// be aware that this one still is not initialized! so:
*tmp = nullptr;
}
Your destructor necessarily fails, too:
Node<T>* ptr, tmp;
for(ptr = head->next; ptr == NULL; ptr = head->next)
{
delete ptr; // you delete ptr, but advancing (ptr = head->next)
// is done AFTERWARDS, so you'd access already deleted memory
// undefined behaviour
}
Additionally, you don't delete the head node! And if head is nullptr, you again have undefined behaviour.
Try it this way:
while(head)
{
Node<T>* tmp = head; // need a copy of pointer
head = head->next; // need to advance BEFORE deleting
delete tmp; // now can delete safely
}

Traversal In linked list

I am new to linked list..My simple code is to create linked list and insert nodes at the end and traverse it..
My problems are-
1)-Every time insert function is called,head pointer gets null
2)-not working right while going in show function..
Please help..Thanks in advance
#include<iostream>
#include<malloc.h>
using namespace std;
struct linkedList
{
int value;
linkedList *next;
};
linkedList* head = NULL;
void insert(linkedList* head, int data)
{
linkedList *ptr;
linkedList *node;
node = (linkedList*) malloc(sizeof(struct linkedList));
node->value = data;
node->next = NULL;
if (head == NULL)
{
head = node;
}
else
{
ptr = head;
while (ptr != NULL)
{
ptr = ptr->next;
}
ptr = node;
}
}
void show(struct linkedList *head)
{
struct linkedList *ptr;
ptr = head;
while (ptr != NULL)
{
cout << ptr->value << endl;
ptr = ptr->next;
}
}
int main()
{
int size = 5;
int array[size];
for (int i = 0; i < 5; i++)
{
cout << "Enter value" << endl;
cin >> array[i];
insert(head, array[i]);
}
show(head);
}
In your insert() function:
when head is NULL, you are assigning the new node to the local head parameter, which is not updating the caller's head variable. That is why your global head variable is always NULL. This is because you are passing the head parameter by value, so you are assigning the new node to a copy, not the original. You need to pass the parameter by reference/pointer instead.
when head is not NULL, you are not traversing the nodes correctly to find the tail node, so ptr is always NULL after the traversal. You are not setting the next field of the tail node at all.
Also, your main() is leaking the allocated nodes.
Try something more like this instead:
#include <iostream>
struct linkedNode
{
int value;
linkedNode *next;
};
void insertValue(linkedNode* &head, int data)
{
linkedNode *node = new linkedNode;
node->value = data;
node->next = NULL;
if (!head)
{
head = node;
}
else
{
linkedNode *ptr = head;
while (ptr->next)
{
ptr = ptr->next;
}
ptr->next = node;
}
}
void showValues(linkedNode *head)
{
linkedNode *ptr = head;
while (ptr)
{
std::cout << ptr->value << std::endl;
ptr = ptr->next;
}
}
void freeValues(linkedNode* &head)
{
linkedNode *ptr = head;
head = NULL;
while (ptr)
{
linkedNode *next = ptr->next;
delete ptr;
ptr = next;
}
}
int main()
{
linkedNode* mylist = NULL;
for (int i = 0; i < 5; ++i)
{
std::cout << "Enter value" << std::endl;
int value;
if (std::cin >> value)
insertValue(mylist, value);
}
showValues(mylist);
freeValues(mylist);
return 0;
}
That being said, if you keep track of the tail node in the list, inserts at the end would be much faster and efficient since you would not need to traverse the list at all:
#include <iostream>
struct linkedNode
{
int value;
linkedNode *next;
linkedNode(int data)
value(data), next(NULL)
{
}
};
struct linkedList
{
linkedNode *head;
linkedNode *tail;
linkedList()
: head(NULL), tail(NULL)
{
}
~linkedList()
{
linkedNode *ptr = head;
while (ptr)
{
linkedNode *next = ptr->next;
delete ptr;
ptr = next;
}
}
void insert(int data)
{
linkedNode *node = new linkedNode(data);
if (!head)
head = node;
if (tail)
tail->next = node;
tail = node;
}
void showValues()
{
linkedNode *ptr = head;
while (ptr)
{
std::cout << ptr->value << std::endl;
ptr = ptr->next;
}
}
};
int main()
{
linkedList mylist;
for (int i = 0; i < 5; ++i)
{
std::cout << "Enter value" << std::endl;
int value;
if (std::cin >> value)
mylist.insert(value);
}
mylist.showValues();
return 0;
}
In which case, you could just throw all of this away and use the standard std::list class instead:
#include <iostream>
#include <list>
#include <algorithm>
void showValue(int value)
{
std::cout << value << std::endl;
}
void showValues(const std::list<int> &values)
{
std::for_each(values.begin(), values.end(), showValue);
/* or, if you are using C++11:
std::for_each(values.begin(), values.end(),
[](int value){ std::cout << value << std::endl; }
);
*/
}
int main()
{
std::list<int> mylist;
for (int i = 0; i < 5; ++i)
{
std::cout << "Enter value" << std::endl;
int value;
if (std::cin >> value)
mylist.push_back(value);
}
showValues(mylist);
return 0;
}

How to determine size of a Linked List without using a while loop?

I need to print out the number of nodes in a linked list. My teacher said that the linked list keeps track of its data and "knows" how many nodes are in it. So, I should not need a while loop to determine the size of the linked list. I have trouble figuring out a way other than a while loop to print out the size.
this is the linked list:
template <class T>
class LinkedList
{
private:
struct ListNode
{
T data ;
struct ListNode * next;
};
ListNode *head;
public:
LinkedList() { head = nullptr; }
~LinkedList();
// Linked list operations
void insertNode(T);
bool deleteNode(T);
void displayList() const;
};
/////////// Implementation portion of linked list with template //////////////
// displayList: print all list data
template <class T>
void LinkedList<T>::displayList() const
{
ListNode * ptr = head;
while (ptr != nullptr)
{
cout << ptr->data << endl;
ptr = ptr->next;
}
}
// insertNode: add a node in list order
template <class T>
void LinkedList<T>::insertNode(T newValue)
{
ListNode *newNode;
ListNode *pCur;
ListNode *pPre = NULL;
newNode = new ListNode;
newNode->data = newValue;
newNode->next = nullptr;
if (head == nullptr)
{
head = newNode;
}
else
{
pCur = head;
pPre = nullptr;
while (pCur != nullptr && pCur->data < newValue)
{
pPre = pCur;
pCur = pCur->next;
}
if (pPre == nullptr)
{
head = newNode;
newNode->next = pCur;
}
else
{
pPre->next = newNode;
newNode->next = pCur;
}
}
}
// deleteNode: delete a node if found
template <class T>
bool LinkedList<T>::deleteNode(T toBeDeleted)
{
ListNode *pCur;
ListNode *pPre;
if (!head)
return true;
pCur = head;
pPre = NULL;
while (pCur != NULL && pCur->data < toBeDeleted)
{
pPre = pCur;
pCur = pCur->next;
}
if (pCur != NULL && pCur->data == toBeDeleted)
{
if (pPre)
pPre->next = pCur->next;
else
head = pCur->next;
delete pCur;
return true;
}
return false;
}
// destructor, delete all nodes
template <class T>
LinkedList<T>::~LinkedList()
{
ListNode *ptr = head;
while (ptr != NULL)
{
head = head->next;
delete ptr;
ptr = head;
}
}
Using the code you've defined, the size of the list is not stored by the list directly. Further to this, the main advantage of linked list is that each node does not know about the rest of the list, and storing the size would defeat the purpose of this.
However, you may have misunderstood what was asked of you in terms of not using a while loop. Each node knows that it's length is 1+(the length of it's tail), and so the more suitable implementation for getting the length of a linked list is recursion, not iteration.
Here is an example of a very simple LinkedList class, that implements the simple methods using recursion. As you can see, the code uses no iteration, only making a check for it's own data, then calling the same method for the next node. Although recursion in procedural languages is less efficient in most cases, for structures like this there is no doubting it is elegant.
#include <iostream>
template<class T>
class LinkedList
{
private:
T data;
LinkedList* next;
public:
LinkedList()
: LinkedList(T()) {
}
LinkedList(T value)
: data(value), next(nullptr) {
}
~LinkedList() {
delete next;
}
void insertNode(T newValue) {
if (!next) {
next = new LinkedList(newValue);
return;
}
next->insertNode(newValue);
}
void displayList() const {
std::cout << data << std::endl;
if (next) {
next->displayList();
}
}
T& at(int N) {
if (N == 0) {
return this->data;
}
return next->at(N-1);
}
int size() {
if (!next) {
return 1;
}
return 1+next->size();
}
};
int main(int argc, char const *argv[])
{
LinkedList<int>* test = new LinkedList<int>(0);
for (int i = 1; i < 10; ++i) {
test->insertNode(i);
}
std::cout << "List of length: " << test->size() << std::endl;
test->displayList();
return 0;
}
You'll notice I haven't included deleteNode, that's because writing it for the oversimplified class above is not possible for the case where the list only has one node. One possible way to implement this is to have a wrapper class, much like you in the original code, that is a pointer to the start of a linked list. See here.