Declaration of Head/First node in a Linked list - c++

Hi all I'm having an issues in a linked list problem. Given two piece of code I've to find why one of them is not working
Code 1 is
struct node {
int data;
struct node *link;
};
void insert(struct node *head) {
struct node *last, *temp;
head = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &head->data);
head->link = NULL;
last = head;
{
int n = 3;
while(n>0){
temp = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &temp->data);
temp->link = NULL;
last->link = temp;
last = temp;
n--;
}
}
return;
}
void display(struct node *p) {
while(p) {
printf("%d ",p->data);
p = p->link;
}
return;
}
int main() {
struct node *head;
insert(head);
display(head);
return 0;
}
and second code is
struct node {
int data;
struct node *link;
}*head;
void insert() {
struct node *last, *temp;
head = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &head->data);
head->link = NULL;
last = head;
{
int n = 3;
while(n>0){
temp = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &temp->data);
temp->link = NULL;
last->link = temp;
last = temp;
n--;
}
}
return;
}
void display(struct node *p) {
while(p) {
printf("%d ",p->data);
p = p->link;
}
return;
}
int main() {
insert();
display(head);
return 0;
}
Now my question is why declaring head in main in the first is not giving o/p for display function wheres declaring it globally in second code is working? Asking this as I'm wondering that in first case head is declared in main and passed as an address so after coming back from insert function it should get the effect of that insert function operation but it's not working like the way and not giving ant o/p for display function

The issue is that, in the first code, insert receives a copy of the main's head pointer and modifies that copy by making it point to some newly allocated memory. That modification never propagates back to main.
To make it propagate, use a pointer to pointer:
void insert(struct node **head) {
struct node *last, *temp;
*head = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &(*head)->data);
(*head)->link = NULL;
last = *head;
{
int n = 3;
while(n>0){
temp = (struct node *)malloc(sizeof(struct node));
printf("Input an integer: ");
scanf("%d", &temp->data);
temp->link = NULL;
last->link = temp;
last = temp;
n--;
}
}
return;
}
and then, in main, call it like so:
insert(&head);
Alternatively, you could make insert take a pointer but also return a pointer (i.e. the new head):
struct node* insert(struct node *head) { ... }
One issue what that API is that it's rather error-prone: it's very easy to call insert() and forget to deal with its return value.

Related

Linked List delete operation not working in visual studio using C

when I tried to implement a linked list in visual studio 2019 using c it produces heap error.
It was due to the free function.
However, the code works fine on online compilers which use the GCC compiler. https://www.jdoodle.com/c-online-compiler/
I can't able to figure it out..........................
here is the code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* head = NULL;
void append(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
(*newNode).data = data;
(*newNode).next = NULL;
if (head == NULL)
{
head = newNode;
return;
}
struct Node* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
void insertAt(int position, int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
newNode->data = data;
newNode->next = NULL;
if (position == 1)
{
newNode->next = head;
head = newNode;
return;
}
struct Node* temp = head;
for (int i = 1; i < position - 1; i++)
{
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
void deleteAt(int position)
{
struct Node* temp = NULL;
if (position == 1)
{
temp = head;
head = temp->next;
free(temp);
return;
}
struct Node* tempHead = head;
for (int i = 1; i < position - 1; i++)
{
tempHead = tempHead->next;
}
temp = tempHead->next;
tempHead->next = temp->next;
free(temp);
}
void print()
{
struct Node* temp = head;
while (temp != NULL)
{
printf("%d\n", temp->data);
temp = temp->next;
}
}
void main()
{
append(3);
append(4);
append(5);
append(6);
insertAt(3, 20);
insertAt(4, 50);
insertAt(2, 70);
deleteAt(4);
deleteAt(3);
print();
}
The sizes you're passing to malloc are wrong. You should pass sizeof(struct Node).
If you're compiling this as C++ you shouldn't be using malloc at all.
As #1201ProgramAlarm answered, the allocation size is wrong. sizeof(struct Node*) is the size of a pointer, not the size of the struct.
Instead of trying to match the type, use the size of the referenced data. Easy to code right, review and maintian.
Cast not needed in C.
// struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
// instead...
// ptr = malloc(sizeof *ptr * N);
struct Node* newNode = malloc(sizeof *newNode);
Just try this code once down there .This code is written by me according to my understanding and still if u have any issue with the code you can further ask me .You can try this code out or just cross check it with your's.
Code:
Linked List:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
}*first=NULL;
void create(int A[],int n)
{
int i;
struct Node *t,*last;
first=(struct Node *)malloc(sizeof(struct Node));
first->data=A[0];
first->next=NULL;
last=first;
for(i=1;i<n;i++)
{
t=(struct Node*)malloc(sizeof(struct Node));
t->data=A[i];
t->next=NULL;
last->next=t;
last=t;
}
}
void Display(struct Node *p)
{
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
}
void RDisplay(struct Node *p)
{
if(p!=NULL)
{
RDisplay(p->next);
printf("%d ",p->data);
}
}
int Delete(struct Node *p,int index)
{
struct Node *q=NULL;
int x=-1,i;
if(index < 1 || index > count(p))
return -1;
if(index==1)
{
q=first;
x=first->data;
first=first->next;
free(q);
return x;
}
else
{
for(i=0;i<index-1;i++)
{
q=p;
p=p->next;
}
q->next=p->next;
x=p->data;
free(p);
return x;
}
}
int main()
{
int A[]={10,20,30,40,50};
create(A,5);
printf(“%d\n",Delete(first),2);
Display(first);
return 0;
}
In main function you can pass the function created int the program and also pass the argument according to you.

Why the elements of the linked list is not showing after changing the return type of the functions create_ll and display from struct node* to void?

I have written a linked list program and want to perform the operation of creating the linked list and displaying the elements of the list. As per the before code the create_ll and display functions both have return type as struct node *. I tried changing the return type to void, but the display function is not displaying the elements. I guess it has something to do with the return of start pointer. What's wrong??
BEFORE:
#include<iostream>
#include<stdlib.h>
using namespace std;
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
struct node *create_ll(struct node *); //create_ll function
struct node *display(struct node *); //display function
int main()
{
start = create_ll(start);
start = display(start);
return 0;
}
struct node *create_ll(struct node *start)
{
struct node *new_node,*ptr;
int num;
cout<<"Enter -1 to end"<<endl;
cout<<"Enter the data: "<<endl;
cin>>num;
while(num!=-1)
{
new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = num;
if(start == NULL)
{
new_node->next = NULL;
start = new_node;
}
else
{
ptr=start;
while(ptr->next != NULL)
ptr=ptr->next;
ptr->next = new_node;
new_node->next = NULL;
}
cout<<"Enter the data"<<endl;
cin>>num;
}
return start;
}
struct node *display(struct node *start)
{
struct node *ptr;
ptr = start;
while(ptr != NULL)
{
cout<<ptr->data<<" ";
ptr = ptr->next;
}
}
AFTER:
#include<iostream>
#include<stdlib.h>
using namespace std;
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
void create_ll(struct node *); //change create_ll function
void display(struct node *); //changed display function
int main()
{
create_ll(start); //changed
display(start); //changed
return 0;
}
void create_ll(struct node *start)
{
struct node *new_node,*ptr;
int num;
cout<<"Enter -1 to end"<<endl;
cout<<"Enter the data: "<<endl;
cin>>num;
while(num!=-1)
{
new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = num;
if(start == NULL)
{
new_node->next = NULL;
start = new_node;
}
else
{
ptr=start;
while(ptr->next != NULL)
ptr=ptr->next;
ptr->next = new_node;
new_node->next = NULL;
}
cout<<"Enter the data"<<endl;
cin>>num;
} //return start; (removed)
}
void display(struct node *start)
{
struct node *ptr;
ptr = start;
while(ptr != NULL)
{
cout<<ptr->data<<" ";
ptr = ptr->next;
}
}
The function
void create_ll(struct node *start);
deals with a copy of the original head node start. So changing the copy does not influence on the value of the original head node.
In the first program you are updating the value of the original head node by the returned value of the changed copy of the node.
start = create_ll(start);
So if you want that the function deal with the original head node (not with its value copy) you have to pass the head node by reference in the C++ meaning ir in C meaning. For example
C++
void create_ll(struct node * &start);
C
void create_ll(struct node **start);
As for the function display then in the first program it has undefined behavior because it returns nothing.:)
start = display(start);
//…
struct node *display(struct node *start)
{
struct node *ptr;
ptr = start;
while(ptr != NULL)
{
cout<<ptr->data<<" ";
ptr = ptr->next;
}
}
If to define a return value of the function then there is a sense to declare the return type as std::ostream &
For example
std::ostream & display( node * start, std::ostream &os = std::cout )
{
for ( node *current = start; current != nullptr; current = current->next )
{
os << current->data << ' ';
}
return os;
}
In this case it can for example be called like
display( start, std::cout << "List: " ) << '\n';
Pay attention to that in C++ you should use the operator new instead of the direct call of the function malloc as you are doing
new_node = (struct node *)malloc(sizeof(struct node));
Change this statement to
new_node = new node;
Because you pass a pointer to start as a copy to your create function and the global one that you have struct node *start = NULL; is not changed and still NULL. Then you pass NULL to your display function and obviously it does not display anything.
You can pass it by reference node *create_ll(node*& start) so that the create function would modify the actual start variable.
Also you don't need to put struct keyword before every node variable declaration in C++.

How to Implement Link List properly in C/C++ without program crashing

I am trying to implement Linked List. In this sample program, user inputs an integer value (the number of strings to store in the list) and then strings one by one... But after several inputs (may be 4 or 5) the program crashes like the image here...
Even, I can't call any function more than 3 times at once which contains malloc() inside them..
I don't know why the problem is occurring. Help me fixing the issue....
#include <bits/stdc++.h>
using namespace std;
typedef struct Linked_List NODE;
struct Linked_List
{
string data;
NODE* next;
};
//Function prototypes
NODE *traverse(NODE *temp);
NODE* createNode(string data);
void preAppend(NODE* ln_list, string x);
NODE* find_data(NODE* ln_list, string data);
int main()
{
NODE* x=createNode("");
int t;
cin >>t;
string z;
while(t--)
{
cin >> z;
preAppend(x, z);
}
traverse(x);
return 0;
}
NODE *traverse(NODE *temp)
{
cout << temp->data << endl;
if(temp->next==NULL) return temp;
traverse(temp->next);
}
NODE* createNode(string data)
{
NODE* node = (NODE*)malloc(sizeof(NODE));
if(node==NULL)
{
printf("Error creating node (Error! Allocating Memory)\n");
exit(1);
}
node->data = data;
node->next = NULL;
}
void preAppend(NODE* ln_list, string x)
{
NODE* new_node = (NODE*)malloc(sizeof(NODE));
if(new_node==NULL)
{
printf("Error! Appending (Error Allocating Memory)\n");
exit(1);
}
new_node->data = x;
new_node->next = ln_list->next;
ln_list->next = new_node;
}
NODE* find_data(NODE* ln_list, string data)
{
NODE* current_node;
current_node = ln_list;
while(current_node->next!=NULL)
{
if(current_node->data == data)
{
return current_node;
}
current_node = current_node -> next ;
}
return NULL;
}
There are several problems in your code:
Usage of malloc instead of new
Using malloc for objects containing c++ objects (like stringin your case) won't call the constructors and therefore any operation upon the non constructed objects will fail.
If your program works without the return statements, it's because of undefined behaviour
Solution:
Replace
NODE* new_node = (NODE*)malloc(sizeof(NODE));
with
NODE* new_node = new NODE;
No return statements in non void functions
NODE *traverse(NODE *temp)
{
cout << temp->data << endl;
if (temp->next == NULL) return temp;
return traverse(temp->next); // return statement is needed here
}
NODE* createNode(string data)
{
NODE* node = new NODE;
if (node == NULL)
{
printf("Error creating node (Error! Allocating Memory)\n");
exit(1);
}
node->data = data;
node->next = NULL;
return node; // return statement needed here
}
Abuse of recursion
Using recursion in traverse may result in a stack overflow for long lists.
You should use a iterative approach. But you've found out that one already.
I uploaded the whole code at once. This method should work without any interruption
although if you want a complete understanding of each part i will recommend you to go over this article that i wrote on my website.
https://www.thebytewise.com/post/data-structure-and-algorithm-using-c-linear-linked-list-thebytewise
#include<stdio.h>
#include<stdlib.h>
void createList();
void traverseList();
struct node{
int data;
struct node *next;
}*header;
int main(){
int n;
printf("Enter the number of elements: ");
scanf("%d", &n);
createList(n);
printf("\nData in the list:\n");
traverseList(n);
return 0;
}
void createList(int n){
struct node *newNode, *temp;
int data, i;
newNode = (struct node *) malloc(sizeof(struct node));
if(newNode == NULL){
printf("ERROR: Memory Overflow");
}
else{
printf("Enter element 1: ");
scanf("%d", &data);
newNode->data = data;
newNode->next = NULL;
header = newNode;
temp = newNode;
for(i=2;i<=n;++i){
newNode = (struct node *) malloc(sizeof(struct node));
if(newNode == NULL){
printf("ERROR: Memory Overflow");
}
else{
printf("Enter element %d: ",i);
scanf("%d",&data);
newNode->data = data;
newNode->next = NULL;
temp->next = newNode;
temp = temp->next;
}
}
}
}
void traverseList(int n){
struct node *temp;
int i;
if(header == NULL){
printf("ERROR: Memory Underflow");
}
else{
temp = header;
for(i=0;i<n;++i){
printf("\ndata %d= %d",i+1, temp->data);
temp = temp->next;
}
}
}

Pairwise Swap of nodes without swapping data in LinkedList

I have been trying to do pairwise swap of linkedlist elements. In place of swapping the elements by data, I am swapping them by swapping the links:
input 1: 1->2->3->4->5
output 1: 2->1->4->3->5
input 2: 1->2->3->4->5->6
output 2: 2->1->4->3->6->5
#include <iostream>
using namespace std;
struct node{
int data;
struct node *next;
};
struct node* func(struct node *f, struct node *s){
if(s==NULL){
return f;
}
struct node *rest1;
rest1 = s->next;
s->next = f;
if(rest1){
f->next = func(rest1,rest1->next);
}
return s;
}
void show(struct node *head){
while(head!=NULL){
cout<<" "<<head->data;
head = head->next;
}
}
int main() {
//code
struct node *head =(struct node*)malloc(sizeof(struct node));
head->data=1;
head->next = (struct node*)malloc(sizeof(struct node));
head->next->data = 2;
head->next->next = (struct node*)malloc(sizeof(struct node));
head->next->next->data = 3;
head->next->next->next = (struct node*)malloc(sizeof(struct node));
head->next->next->next->data = 4;
//head->next->next->next->next=(struct node*)malloc(sizeof(struct node));
//head->next->next->next->next->data=5;
head = func(head,head->next);
show(head);
return 0;
}
This code works fine for odd length list but does not work for even length.
I think the problem is in:
if(s==NULL){
return f;
}
statement which I am using to make previous f->next=NULL (in case of even length).
Since you tagged this as C++, I'd recommend STL's <list>. You can accomplish what you want with its splice method which allows you to manipulate the list. One possible implementation would look something like:
void alternate(list<int>& l)
{
if (l.empty())
return;
auto from_itr = cbegin(l);
auto to_itr = from_itr;
for (; ++to_itr != cend(l) && ++to_itr != cend(l);) {
l.splice(to_itr, l, from_itr);
++from_itr;
}
}
NOTE: The from_itr in the loop is incremented only once because it has been moved in the list to precede the next node of interest.
Consider the case of Even length list say 1->2->3->4->5->6 when f points to 5, s points to 6 & rest1 points to null.
s->next = f makes node 6->5 but still node 5 will point to 6. Thus a loop will be formed where 6->5->6->5..............so on.
Thus to make this code work add an else statement here
if(rest1){
f->next = func(rest1,rest1->next);
}
else f->next = NULL;
This will make 5->NULL preventing an infinite loop.Thus your function will look like this
struct node* func(struct node *f, struct node *s){
if(s==NULL){
return f;
}
struct node *rest1;
rest1 = s->next;
s->next = f;
if(rest1){
f->next = func(rest1,rest1->next);
}
else f->next = NULL;
return s;
}

inserting element at the end of linked list

I am trying to insert element at the end of linked list but the while loop doesn't terminate. I am not able to understand why is this happening. Here is my code.
I am calling this function inside my main() function.
struct node{
int data;
struct node* link;
};
struct node * head;
void insert_last(int element){
struct node * temp = (node*)malloc(sizeof(struct node));
temp->data = element;
temp->link = NULL;
if(head==NULL){
head = temp;
}
struct node * temp1 = head;
while(temp1->link!=NULL){
temp1 = temp1->link;
}
temp1->link = temp;
}
Here is the main method:
int main()
{
head = NULL;
printf("Enter the no. of nodes or elements you want to make linked list of. ");
int n;
scanf("%d",&n);
int element = 0;
for(int i = 0; i<n; i++){
printf("Enter the element\n");
scanf("%d",&element);
insert_last(element);
std::cout<<"Element inserted\n\n";
}
//print_recursive(head);
print();
}
That's easy.
if(head==NULL){
head = temp;
}
In that case, you are already done with what are you doing. If you continue, temp1 becomes the temp. Then temp1->link = temp; makes this node point to itself. Second insertion will never find end because your list is circular now and while(temp1->link!=NULL) will never end.
What you should do is simply put return;.
if(head==NULL){
head = temp;
return;
}