After exiting from function, nodes aren't saved - c++

My program should create a linked list and show it. My problem is when the addelemnt_end function ends, it doesn't update head and last.
I tried with debug and when my function is done, the info and next part from head and last are "unable to read memory".
struct node{
int info;
node *next;
};
node *head, *last;
void addelement_end(node *head, node *last, int element)
{if (head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
last = temp;
head = temp;
}
else {node*temp = new node;
last->next = temp;
temp->info = element;
temp->next = NULL;
last = temp;
}
}
void show(node* head, node *last)
{
if (head==NULL)
cout << "Empty list";
else
while (head != NULL)
{
cout << head->info << " ";
head = head->next;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int x, n, i;
cout << "how many numbers";
cin >> n;
head = last = NULL;
for (i =1; i <= n; i++)
{
cin >> x;
addelement_end(head, last, x);
}
show(head, last);
return 0;
}

It's a very common error. Here is a similar illustration of the problem:
int change_a(int a) {
a = 42;
}
int main() {
int a = 10;
change_a(a);
printf("%d\n", a);
return 0;
}
This will print 10 because in the function change_a you are only modifying a copy of the value contained in the variable a.
The correct solution is passing a pointer (or using a reference since you are using C++).
int change_a(int *a) {
*a = 42;
}
int main() {
int a = 10;
change_a(&a);
printf("%d\n", a);
return 0;
}
But maybe you're going to tell me: "I'm already using a pointer!". Yes, but a pointer is just a variable. If you want to change where the pointer points, you need to pass a pointer to that pointer.
So, try this:
void addelement_end(node **head, node **last, int element)
{
if (*head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
*last = temp;
*head = temp;
}
else {
node *temp = new node;
(*last)->next = temp;
temp->info = element;
temp->next = NULL;
*last = temp;
}
}

Related

How to use head while iterating through a linked list?

We are iterating through the linked list with the help of head, that is, we are updating our head as we move forward towards i th position. Please have a look at the fuction insertIthnode. I am inserting my Node at i th position are returning head - and it's still able to print the linked list. I don't know how? head is no longer pointing towards the first node then how is it still able to return a full linked list?
here's the code:
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
next = NULL;
}
};
int length(Node *head) {
int x = 0;
Node *temp = head;
while (temp != NULL) {
x += 1;
temp = temp->next;
}
return x;
}
void printIthnode(Node *head, int i) {
int n = length(head);
if (i < 0 || i > n - 1) {
cout << -1 << endl;
return;
}
int count = 1;
while (count <= i) {
head = head->next;
count++;
}
if (head) {
cout << head->data << endl;
} else {
cout << "-1" << endl;
}
}
Node *takeinput() {
int data;
cin >> data;
Node *head = NULL;
Node *tail = NULL;
while (data != -1) {
Node *n = new Node(data);
if (head == NULL) {
head = n;
tail = n;
} else {
tail->next = n;
tail = n;
}
cin >> data;
}
return head;
}
void PrintLL(Node *head) {
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
Node *insertIthnode(Node *head, int i, int data) {
if (i < 0) {
return head;
} else if (i == 0) {
Node *n = new Node(data);
n->next = head;
head = n;
return head;
}
int count = 1;
while (count <= i - 1 && head != NULL) {
head = head->next;
count++;
if (count == i - 1) {
Node *n = new Node(data);
n->next = head->next;
head->next = n;
return head;
}
return head;
}
}
int main() {
/*Node n1(1);
Node *head=&n1;
Node n2(2);
Node n3(3);
Node n4(4);
Node n5(5);
Node n6(6);
n1.next=&n2;
n2.next=&n3;
n3.next=&n4;
n4.next=&n5;
n5.next=&n6;
*/
Node *head = takeinput();
insertIthnode(head, 3, 7);
PrintLL(head);
}
In the main() function you are creating a head when you are taking input from the user with the help of the "takeInput()" function.
After that, you are calling the function "insertIthnode(head,3,7)" which is returning the head (since the return type is Node) but you are not receiving it in any variable so the head returned from the "insetIthnode" is lost.
Your original head remains the same as per of "takeInput()" function.
If you try to insert ith Node at Index 0 it won't print according to the inserted node.
The problem is that you consider the Node as the linked list. While this is valid, the whole point of the linked list is that you don't lose track of the head. You could use two approaches:
Don't iterate over the head. Instead, use a temporary reference to the head.
Implement a Linked List wrapper. You can keep a constant reference to the head while performing operations over the node.
You pass head by value. Any changes you do to the variable receiving the value of head inside the functions are made to the local variable inside the function only and will not be visible from the call site.
Take your PrintLL function as an example:
void PrintLL(Node *head) { // head is here a local variable
Node *temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
This could be rewritten without the extra variable temp. The name head doesn't make it the same head you used to call the function with:
void PrintLL(Node* head) {
while (head != nullptr) {
cout << head->data << ' ';
head = head->next;
}
}
and it would not affect the head you passed in as a parameter.
Similarly:
void foo(int x) {
++x;
//
}
int main() {
int x = 10;
foo(x);
std::cout << x << '\n'; // prints 10
}

LinkedList not working properly in gcc compiler

So i am using mingwx64 compiler and vscode editor but display function is not working properly but when i try to display in main() function with same logic as arr.display() It works.
I tried running the same code on onlinegdb website and it was running as intended.
Is is a gcc bug or a feature i am not aware of ?
#include <iostream>
using namespace std;
class nodee
{
public:
int data;
nodee *next;
};
class ll
{
public:
nodee **head = NULL;
nodee **push(int no = 1)
{
nodee *node;
int n;
if (head != NULL)
{
node = *head;
while ((*node).next != NULL)
{
node = (*node).next;
}
while (no--)
{
nodee *new_node = new nodee();
cout << "Enter the element : ";
cin >> n;
(*node).next = new_node;
new_node->data = n;
new_node->next = NULL;
node = (*node).next;
}
}
else
{
nodee *first = new nodee();
head = &first;
node = *head;
cout << "Enter the element : ";
cin >> n;
first->data = n;
no--;
while (no--)
{
nodee *new_node = new nodee();
cout << "Enter the element : ";
cin >> n;
(*node).next = new_node;
new_node->data = n;
new_node->next = NULL;
node = (*node).next;
}
}
return head;
}
void display()
{
nodee *node = *head;
while (node->next != NULL)
{
cout << node->data<<endl;
node = node->next;
}
cout<<node->data<<endl;
}
};
int main()
{
ll arr;
arr.push(5);
arr.display();
return 0;
}
The error is head = &first;, you are using a pointer to a local variable as head, which is invalid after the push function.
The solution is to make head only be a nodee *, you do not need the extra *:
#include <iostream>
using namespace std;
class nodee
{
public:
int data;
nodee *next;
};
class ll
{
public:
nodee *head = NULL;
nodee *push(int no = 1)
{
nodee *node;
int n;
if (head != NULL)
{
node = head;
while ((*node).next != NULL)
{
node = (*node).next;
}
while (no--)
{
nodee *new_node = new nodee();
cout << "Enter the element : ";
cin >> n;
(*node).next = new_node;
new_node->data = n;
new_node->next = NULL;
node = (*node).next;
}
}
else
{
nodee *first = new nodee();
head = first;
node = head;
cout << "Enter the element : ";
cin >> n;
first->data = n;
no--;
while (no--)
{
nodee *new_node = new nodee();
cout << "Enter the element : ";
cin >> n;
(*node).next = new_node;
new_node->data = n;
new_node->next = NULL;
node = (*node).next;
}
}
return head;
}
void display()
{
nodee *node = head;
while (node->next != NULL)
{
cout << node->data<<endl;
node = node->next;
}
cout<<node->data<<endl;
}
};
int main()
{
ll arr;
arr.push(5);
arr.display();
return 0;
}
not working: https://godbolt.org/z/cr4rY4oKK
working: https://godbolt.org/z/88rd53jGP
Your declaration of the list does not make a sense.
Instead of declaring the data member head like
nodee *head = NULL;
you declared it like
nodee **head = NULL;
Within the function push when it is called the first time the pointer head is set by the address of the local variable first that will not be alive after exiting the function
nodee *first = new nodee();
head = &first;
So the pointer head will be invalid.
Also the function push has a confusing logic. What is should do is to push an integer value on the list. So its parameter should specify the value that will be pushed not the number of nodes that will be pushed.
That is the function should be declared like
void push( int data );
Pay attention to that if you have a one-sided singly-linked list then new nodes should be appended to the beginning of the list. Otherwise you need to define a two-sided singly-linked list that is you need to declare a pointer to the head node and to the tail node..
For the one-sede linked-list the function push can be defined the following way provided that the data member head is declared like
nodee *head = NULL;
void push( int data )
{
nodee *mew_node = new nodee { data, head };
head = new_node;
}

Trying to initialize a linked list using array

I need to define a class of linked list,List, in a way such that object of class can be defined in two ways,
List obj1 = L1();//head=0
List obj2 = L2(given_arr[], size of array) // I would be given an array, whose elements are elements of list
so, I need to form a construter for both,
for obj1, Its easy.
List(){head=0};
But I am not abe to do so for second type of object.
I tried to form a program for this.
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head;
int arr[];
List() { head = 0; }
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
int i;
head->val = arr[0];
for (i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[4] = {9, 89, 0, 43};
List* M = new List();
List* L = new List(barr[4], 4);
L->display();
return 0;
}
This program doesn't work. Please suggest a way to do so.
Make these changes to your main().
int main() {
int barr[] = {9, 89, 0, 43}; // No need to specify size if you're initializing
// List* M = new List(); // unused
// Your array is barr, barr[4] makes no sense. You also don't allocate the List,
// the list allocates
List L = List(barr, sizeof(barr) / sizeof(barr[0]);
L.display(); // -> to .
return 0;
}
This now compiles, but immediately segfaults. Simply running the program in the debugger shows a simple error. The line head->val = arr[0]; attempts to dereference a null pointer. Which takes us to the next thing. Use nullptr, not NULL or 0.
Your array constructor was over-complicated, you just need this:
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
Your addnode() function already handled an empty list. Fixing that, your code should run. I made a couple other small changes, mostly trimming cruft out. Here's your complete code:
#include <iostream>
using namespace std;
class List {
class node {
public:
int val;
node* next;
};
public:
node* head = nullptr;
List() = default;
List(int arr[], int size);
void addnode(int value) {
node* newnode = new node();
newnode->val = value;
newnode->next = NULL;
if (head == NULL) {
head = newnode;
} else {
node* temp = head; // head is not NULL
while (temp->next != NULL) {
temp = temp->next; // go to end of list
}
temp->next = newnode; // linking to newnode
}
}
void display() {
if (head == NULL) {
cout << "List is empty!" << endl;
} else {
node* temp = head;
while (temp != NULL) {
cout << temp->val << " ";
temp = temp->next;
}
cout << endl;
}
}
};
List::List(int arr[], int size) {
for (int i = 0; i < size; i++) addnode(arr[i]);
}
int main() {
int barr[] = {9, 89, 0, 43};
List L = List(barr, sizeof(barr) / sizeof(barr[0]));
L.display();
return 0;
}

Printing the singly linked list

I am a newbie to programming
Here I wrote a code for accepting and displaying the values using linked list.
However the code takes all the values but displays only the last value
Here is the code
#include <iostream>
using namespace std;
struct node {
int value;
node* next;
};
class llist {
public:
void create();
void display();
node* head = NULL;
};
void llist::create()
{
struct node* temp;
temp = NULL;
struct node* p;
p = new struct node;
cin >> p->value;
if (head == NULL) {
head = p;
}
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
}
void llist::display()
{
struct node* temp = head;
while (temp != NULL) {
cout << "VALUE:" << temp->value << endl;
temp = temp->next;
}
}
int main()
{
int n, i;
llist l1;
cin >> n;
for (i = 0; i < n; i++)
l1.create();
cout << "Displaying list\n";
l1.display();
return 0;
}
Input:
4
1
2
3
4
Displaying list
VALUE:4
I am wondering what went wrong...
Change this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->value = p->value;
temp->next = NULL;
}
to this:
else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
}
When inserting a new element at the end of a linked list, you find the last element inside the while loop and put it in the temp variable. Then you assign its next value to your new p element. The way you were doing before, you were just overriding the integer number of the last element. That is why when you printed your list you only got the last number you entered.
Also, when creating a new element p, be sure to initialize its next value to NULL:
p = new struct node;
p->next = NULL;
Problem is with the last 2 lines in the else block.
You are overwriting the value and maintaining just the single mode in your list class. And that's the reason, only last value is displayed.
Replace
temp->value = p->value;
temp->next = NULL;
With
temp->next = p;

Adding nodes to linked list

struct ll
{
int data;
ll *next;
};
void display(ll **head) {
ll *t = *head;
while(t){
cout<<t->data<<"-->";
t = t->next;
}
}
void add(ll **head, int d) {
ll *c = *head;
ll temp;
temp.data = d;
temp.next = NULL;
if(*head == NULL) {
*head = &temp;
} else {
while(c->next) {
c = c->next;
}
c->next = &temp;
}
}
int main() {
ll *head = NULL;
add(&head,1);
add(&head,2);
//add(&head,3);
//add(&head,4);
//add(&head,10);
//display(&head);
getchar();
}
why does using ll temp in add() not work. if i convert this to ll *temp= new ll; all w
Your Add() function creates a local ll struct.
Accessing it leads to undefined behavior.
You need to allocate your nodes at the heap section of the memory.
void add(ll **head, int d) {
ll *c = *head;
ll *temp = new ll;
temp->data = d;
temp->next = NULL;
if(*head == NULL) {
*head = temp;
} else {
while(c->next) {
c = c->next;
}
c->next = temp;
}
}
You created a local struct in your function which goes out of scope (all memory is released at the end of the function). However, as you pointed your node to it: *head = &temp;, it will cause undefined behaviour as it will point to destroyed memory at the end of the function (once temp has gone out of scope), which is unsafe to dereference.
However, if temp is allocated with new, it means that the temp's will not be destroyed until you call the delete keyword, allowing it to be safe to effectively point to a variable created in the function.
Try this:
struct ll
{
int data;
ll *next;
};
void display(ll** head)
{
ll* cur = *head;
while(cur != NULL){
cout<< cur->data << "-->";
cur = cur->next;
}
}
void add(ll** head, int d)
{
ll* cur = *head, *temp = new ll;
temp->data = d;
temp->next = NULL;
if(*head == NULL) {
*head = temp;
}
else {
while(cur->next != NULL) {
cur = cur->next;
}
c->next = temp;
}
}
void free_list(ll** head)
{
ll* cur = *head, *next = NULL;
while(cur != NULL){
next = cur->next;
delete cur;
cur = next;
}
}
int main()
{
ll *head = NULL;
add(&head,1);
add(&head,2);
display(&head);
free_list(&head);
getchar();
}