Linked list traversal after reversing the linked list - c

I've been trying to run this linkedListTraversal() function after reversing the linked list using the function reverseLinkedList(). I know that I'm applying the correct logic in the reverseLinkedList() function. But for some reason i'm getting the output as something like this
Here's my code
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
// struct Node *head;
void linkedListTraversal(struct Node *ptr)
{
// struct Node *ptr = head;
while (ptr != NULL)
{
printf("Element: %d\n", ptr->data);
ptr = ptr->next;
}
}
void reverseLinkedList(struct Node *head)
{
struct Node *prevNode = NULL;
struct Node *currNode = head;
struct Node *nextNode;
while (currNode != NULL)
{
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
}
int main()
{
struct Node *head;
struct Node *second;
struct Node *third;
head = (struct Node *)malloc(sizeof(struct Node));
second = (struct Node *)malloc(sizeof(struct Node));
third = (struct Node *)malloc(sizeof(struct Node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printf("Linked list before reversal: \n");
linkedListTraversal(head);
reverseLinkedList(head);
printf("Linked list after reversal: \n");
linkedListTraversal(head);
return 0;
}

You're not passing back the updated head to main.
The easiest way is to return the head:
struct Node *reverseLinkedList(struct Node *head);
And have main do:
head = reverseLinkedList(head);
Side note: No need to cast the results of malloc: Do I cast the result of malloc? Here's a more idiomatic way to allocate (e.g.):
head = malloc(sizeof(*head));
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
// struct Node *head;
void
linkedListTraversal(struct Node *ptr)
{
// struct Node *ptr = head;
while (ptr != NULL) {
printf("Element: %d\n", ptr->data);
ptr = ptr->next;
}
}
struct Node *
reverseLinkedList(struct Node *head)
{
struct Node *prevNode = NULL;
struct Node *currNode = head;
struct Node *nextNode;
while (currNode != NULL) {
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
return head;
}
int
main(void)
{
struct Node *head;
struct Node *second;
struct Node *third;
head = malloc(sizeof(*head));
second = malloc(sizeof(*second));
third = malloc(sizeof(*third));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printf("Linked list before reversal: \n");
linkedListTraversal(head);
head = reverseLinkedList(head);
printf("Linked list after reversal: \n");
linkedListTraversal(head);
return 0;
}

Related

Duplicating a linked list without using recursion

I'm trying to figure out how to duplicate a linked list, and after debugging on Vs code I'm getting a segmentation fault on cuurent->data = temp->data;
and I'm not sure why this is happening.
and this is the code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head;
struct node* head2;
struct node* Insert(struct node* head, int x)
{
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = head;
return temp;
}
void Print(struct node* head)
{
struct node* tmp1 = head;
printf("List is:");
while (tmp1 != NULL) {
printf(" %d", tmp1->data);
tmp1 = tmp1->next;
}
printf("\n");
}
struct node* dupe(struct node* head, struct node* head2)
{
if (head == NULL)
return NULL;
struct node* temp = head;
struct node* prev = NULL;
struct node* cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
if (head2 == NULL) {
cuurent->next = head2;
head2 = cuurent;
}
while (temp != NULL) {
temp = temp->next;
cuurent = (struct node*)malloc(sizeof(struct node));
cuurent->data = temp->data;
cuurent->next = prev;
prev = cuurent;
}
return head2;
}
int main(void)
{
head = NULL;
head2 = NULL;
head = Insert(head, 4);
head = Insert(head, 2);
head = Insert(head, 3);
head = Insert(head, 5);
head2 = dupe(head, head2);
Print(head);
Print(head2);
}
As pointed out in the comments,
while (temp != NULL) {
temp = temp->next;
changes the value of temp immediately after guarding against a null pointer value.
This eventually means
cuurent->data = temp->data;
will cause Undefined Behaviour by dereferencing temp when it is the null pointer value.
You can apply the exact same looping principles shown in Print to copy the list. The only difference being you must save a pointer to the first node.
The same principle can be used again when it comes time to free the memory.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *next, int x)
{
struct node *n = malloc(sizeof *n);
n->data = x;
n->next = next;
return n;
}
void print_list(struct node *head)
{
printf("List is: ");
while (head) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
void free_list(struct node *head)
{
struct node *t;
while (head) {
t = head->next;
free(head);
head = t;
}
}
struct node *copy_list(struct node *head)
{
struct node *root = NULL;
for (struct node *current; head; head = head->next) {
struct node *new = insert(NULL, head->data);
if (!root)
root = new;
else
current->next = new;
current = new;
}
return root;
}
int main(void)
{
struct node *head = NULL;
head = insert(head, 4);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 5);
struct node *head2 = copy_list(head);
print_list(head);
print_list(head2);
free_list(head);
free_list(head2);
}
Output:
List is: 5 3 2 4
List is: 5 3 2 4

Can't insert a node at the beginning of a linked list using a void function

I m trying to insert a newNode at the beginning of a linked list in C language. I have tried other methods such as returing the newNode from the insertAtBeginnning function and then setting the head as that newNode in the main function & that works fine. But what I want to do is use a void function for the case and change the head there itself which is not working.
Here's the complete code :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void linkedListTraversal(struct Node *ptr)
{
while (ptr != NULL)
{
printf("element: %d\n", ptr->data);
ptr = ptr->next;
}
}
void insertAtBeginning(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = head;
head = newNode;
}
void insertAtIndex(struct Node *head, int data, int index)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
int i = 0;
while (i < index - 1)
{
temp = temp->next;
i++;
}
newNode->data = data;
newNode->next = temp->next;
temp->next = newNode;
}
void insertAtEnd(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode;
newNode->data = data;
newNode->next = NULL;
}
void insertAfterNode(struct Node *previous, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = previous->next;
previous->next = newNode;
}
int main()
{
struct Node *head;
struct Node *second;
struct Node *third;
struct Node *fourth;
// Allocate memory for the nodes of the linkedLists in the heap
head = (struct Node *)malloc(sizeof(struct Node));
second = (struct Node *)malloc(sizeof(struct Node));
third = (struct Node *)malloc(sizeof(struct Node));
fourth = (struct Node *)malloc(sizeof(struct Node));
// Link first and second nodes
head->data = 12;
head->next = second;
// Link second and third nodes
second->data = 98;
second->next = third;
// Link third and fourth nodes
third->data = 38;
third->next = fourth;
// Terminate the linkedList at the fourth node
fourth->data = 37;
fourth->next = NULL;
printf("Linked list before insertion\n");
linkedListTraversal(head);
insertAtBeginning(head, 20);
// insertAtIndex(head, 22, 3);
// insertAtEnd(head, 110);
// insertAfterNode(second, 27);
printf("Linked list after insertion\n");
linkedListTraversal(head);
return 0;
}
Here i have also used other cases of insertion in linked list and all are working fine instead of just insertAtBeginning function :(
Any help will be greatfull.
head is the entry point for your list. Inserting an element at the beginning should make head point to this new element. To do it from a void function, you have to pass the address of head so that head is modified by the function:
void insertAtBeginning(struct Node **head, int data)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
The call to the function will therefore be:
insertAtBeginning(&head, 20);
Another solution would be to have the function return the new address of head.
PS: we don't cast the return from malloc in C and we should check that it succeeded.

Linked List not printing

I am trying to create a simple linked list using C, I think I was able to construct the linked list itself, but when I try and print it, it prints the value of the last node instead of all the values in the list.
#include <stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
temp->next = NULL;
printf("%d \n", temp->d);
return 0;
}
Any help/tips would be greatly appreciated.
There are multiple problems in your code:
You are not creating the list properly. You are allocating memory for only one node and playing around with pointers improperly causing the linked list to be pointed to the same memory
You are not calling printList function at all
It is not clear why you are allocating memory again in printList whereas it should be printing the already created list
Also, no need to pass double pointer for printList as you are not modifying the list.
Though you should be understanding and doing the changes yourself, I am providing a below modified program which I hope will help you understand the mistakes in your code.
Please see the below modified version of the code
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
struct Node *createNode()
{
struct Node *newNode;
newNode = malloc(sizeof(struct Node));
if (NULL == newNode)
return NULL;
memset(newNode, 0, sizeof(struct Node));
return newNode;
}
int main()
{
struct Node *newNode = NULL;
struct Node *headNode = NULL;
struct Node *temp = NULL;
int i = 0;
int data = 0;
printf("Enter 3 numbers\n");
for( i = 0; i< 3; i++)
{
scanf("%d", &data);
newNode = createNode();
if (NULL == newNode)
break;
newNode->d = data;
if (headNode == NULL)
{
headNode = newNode;
temp = newNode;
}
else
{
temp->next = newNode;
temp = temp->next;
}
}
printList(headNode);
return 0;
}
Replace your code with the following code :-
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp->next!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
printList(head);
return 0;
}
Here you need to declare the newNode in the loop also while taking the input. As, the current value is over-writted, the old value is lossed and only the value of last node is printed.
Also while printing, check for temp->next!=Null instead of temp!=NULL

Linked List Program is crashing again and again

I have made a sorted linked list program. I don't know why, but it is crashing again and again. Tried to fix it but, didn't work. The problem seems to be in a print_list function, but don't know what's the problem.
here's my code.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node{
struct node *next;
int val;
};
struct LLADT{
struct node *head;
};
void init(struct LLADT *LL){
LL-> head = 0;
}
// Printing a linked list
void print_list(struct LLADT *LL){
struct node *temp;
temp = LL-> head;
while(temp ->next!=NULL){ // changed temp!=NULL to temp->next!=NULL
printf("%d\n", temp->val);
temp = temp -> next;
}
}
//inserting sorted elements
void sortInsert(struct LLADT *LL, int num){
struct node *newNode;
newNode->val = num;
newNode->next = 0;
newNode =(struct node*)malloc(sizeof(struct node));
// Case -1: List is empty
if(LL->head == 0){
LL->head = newNode;
}
else{
struct node *curr;
curr = LL->head;
struct node *prev;
prev = NULL;
// Traversing list to find the insert location
while(curr != 0){
if(curr->val >= newNode->val){
break;
}
else{
prev = curr;
curr = curr -> next;
}
// Case-2:
if(curr == LL->head){
newNode->next = LL->head;
LL->head = newNode;
}
// case-3
else{
newNode->next = curr;
prev->next = newNode;
}
}
}
}
int main(){
struct LLADT LL;
sortInsert(&LL,17);
sortInsert(&LL,3);
sortInsert(&LL,5);
sortInsert(&LL,2);
sortInsert(&LL,1);
sortInsert(&LL,20);
//print_list(&LL);
getch();
return 0;
}
using codeblocks.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node{
struct node *next;
int val;
};
/*struct LLADT{
struct node *head;
};*/
struct node * head ;
void init(){
head = NULL;
}
// Printing a linked list
void print_list(){
struct node *temp;
temp = head;
while(temp !=NULL){
printf("%d\n", temp->val);
temp = temp -> next;
}
}
//inserting sorted elements
void sortInsert(int num){
struct node *newNode;
struct node *curr;
newNode =(struct node*)malloc(sizeof(struct node));
newNode->val = num;
newNode->next = NULL;
// Case -1: List is empty
if(head == NULL){
head = newNode;
}
else{
curr=head;
while(curr->next!=NULL){
curr=curr->next;
}
curr->next=newNode;
// Traversing list to find the insert location
// while(curr != NULL){
// if(curr->val >= newNode->val){
// break;
// }
// else{
// prev = curr;
// curr = curr -> next;
// }
// Case-2:
// if(curr == LL->head){
// newNode->next = LL->head;
// LL->head = newNode;
//}
// case-3
//else{
// newNode->next = curr;
// prev->next = newNode;
// }
//}
}
}
int main(){
//struct LLADT LL;
sortInsert(17);
sortInsert(3);
sortInsert(5);
sortInsert(2);
sortInsert(1);
sortInsert(20);
print_list(head);
getch();
return 0;
}
You can try this code as there is no need to declare other struct for head
Commented out your unwanted code

C: How to free nodes in the linked list?

How will I free the nodes allocated in another function?
struct node {
int data;
struct node* next;
};
struct node* buildList()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
}
I call the buildList function in the main()
int main()
{
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
}
I want to free head, second and third variables.
Thanks.
Update:
int main()
{
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
}
Both prints 2. Shouldn't calling free(h) remove h. If so why is that h->next->data available, if h is free. Ofcourse the 'second' node is not freed. But since head is removed, it should be able to reference the next element. What's the mistake here?
An iterative function to free your list:
void freeList(struct node* head)
{
struct node* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
What the function is doing is the follow:
check if head is NULL, if yes the list is empty and we just return
Save the head in a tmp variable, and make head point to the next node on your list (this is done in head = head->next
Now we can safely free(tmp) variable, and head just points to the rest of the list, go back to step 1
Simply by iterating over the list:
struct node *n = head;
while(n){
struct node *n1 = n;
n = n->next;
free(n1);
}
One function can do the job,
void free_list(node *pHead)
{
node *pNode = pHead, *pNext;
while (NULL != pNode)
{
pNext = pNode->next;
free(pNode);
pNode = pNext;
}
}
struct node{
int position;
char name[30];
struct node * next;
};
void free_list(node * list){
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
{
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
}
}
You could always do it recursively like so:
void freeList(struct node* currentNode)
{
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
}

Resources