Reversing The Last 5 Nodes In A Linked List - c

I want to reverse the last 5 nodes in a linked list as follows:
Input: 2->4->6->8->10->12->14->16->NULL
Output: 2->4->6->16->14->12->10->8->NULL
I have written the following code to perform the above task but my reverse() function is not working.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
int n;
void insert(struct node **headref, int data) {
struct node *new_node;
new_node = malloc(sizeof(struct node));
new_node->data = data;
new_node->next = *headref;
*headref = new_node;
}
struct node* create() {
struct node dummy;
struct node *new_node = &dummy;
dummy.next = NULL;
int i,num;
printf("Enter The Number Of Data: ");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
printf("Enter Data %d: ", i);
scanf("%d", &num);
insert(&(new_node->next), num);
new_node = new_node->next;
}
return dummy.next;
}
void display(struct node *head) {
struct node *current;
for(current = head; current != NULL; current = current->next) {
printf("%d ", current->data);
}
printf("\n");
}
void reverse(struct node *head) {
struct node *current, *next, *prev, *temp;
current = head;
next = current->next;
prev = NULL;
int i;
for(i = 0; i < n-5; i++) {
temp = current;
current = next;
next = next->next;
}
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
temp->next = prev;
}
int main() {
struct node *start = create();
display(start);
reverse(start);
display(start);
}
Is there any error in my logic in the reverse() function? I tried the dry run on paper and it should have worked but it isn't working. Please point out the mistake that I made or even better suggest some alternative code to solve this problem.

The problem is in the line:
next = next->next;
in this part of the code:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
In the last element, when current becomes the last node current->next is NULL and you try to get next->next->next which gives segmentation fault.
You need to change the above line simply by adding an if statement:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
if (next!=NULL) next = next->next;
}
I tried with your given input and it works!!

Related

Copying elements of a linked list to another linked list in reverse order in C

I'm new to programming in C and taking a course. I'm having trouble with one of the tasks I'm practicing. I'm supposed to Write a program that creates a linked list of 10 characters, then creates a copy of the list in reverse order. I have written (mostly copied) a code, but it only reverses the contents of my linked list, doesn't copy them to a new linked list in reverse order. It's also not working with letters even though I'm using char data type. works fine with numbers.
Here's my code:
#include <stdio.h>
#include <malloc.h>
struct Node
{
char data;
struct Node *next;
};
static void reverse(struct Node **head_ref)
{
struct Node *previous = NULL;
struct Node *current = *head_ref;
struct Node *next;
while (current != NULL)
{
next = current->next;
current->next = previous;
previous = current;
current = next;
}
*head_ref = previous;
}
void push(struct Node **head_ref, char new_data)
{
struct Node *new_node =
(struct Node *)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printList(struct Node *head)
{
struct Node *temp = head;
while (temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
int main()
{
struct Node *head = NULL;
char element = NULL;
printf("Enter 10 characters:\n");
for (int i = 0; i <= 9; i++)
{
scanf_s("%d", &element);
push(&head, element);
}
printf("Given linked list\n");
printList(head);
reverse(&head);
printf("\nReversed Linked list \n");
printList(head);
getchar();
}
This for loop
for (int i = 0; i <= 9; i++)
{
scanf_s("%d", &element);
push(&head, element);
}
invokes undefined behavior because there is used an incorrect conversion specifier %d with an object of the type char,
You need to write
for (int i = 0; i <= 9; i++)
{
scanf_s( " %c", &element, 1 );
push(&head, element);
}
Pay attention to the blank before the conversion specifier %c in the format string. This allows to skip white space characters in the input stream.
As for the function then it can be declared and defined the following simple way using the function push that you already defined
struct Node * reverse_copy( const struct Node *head )
{
struct Node *new_head = NULL;
for ( ; head != NULL; head = head->next )
{
push( &new_head, head->data );
}
return new_head;
}
And in main you can write something like
struct Node *second_head = reverse_copy( head );
Take into account that the function push would be more safer if it would process the situation when memory allocation for a node failed.
To create a copy in reverse order, create a new list with the same values as the original list but prepend the new nodes using the push function.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct Node {
char data;
struct Node *next;
};
void prepend(struct Node **head_ref, char new_data) {
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void append(struct Node **head_ref, char new_data) {
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
struct Node *node = *head_ref;
new_node->data = new_data;
new_node->next = NULL;
if (!node) {
*head_ref = new_node;
} else {
while (node->next)
node = node->next;
node->next = new_node;
}
}
void printList(const struct Node *head) {
const struct Node *temp = head;
while (temp != NULL) {
printf("%c ", temp->data);
temp = temp->next;
}
printf("\n");
}
struct Node *copy_reverse(struct Node *list) {
struct Node *new_list = NULL;
while (list) {
prepend(&new_list, list->data);
list = list->next;
}
return new_list;
}
void freeList(struct Node *list) {
while (list) {
struct Node *node = list;
list = list->next;
free(node);
}
}
int main() {
struct Node *head = NULL;
char element;
printf("Enter 10 characters:\n");
for (int i = 0; i < 10; i++) {
scanf_s("%c", &element);
push(&head, element);
}
printf("Given linked list\n");
printList(head);
struct Node *copy = copy_reverse(head);
printf("\nReversed Linked list \n");
printList(copy);
freeList(head);
freeList(copy);
getchar();
}
You're almost there. All it needs is one tweak. In reverse, you need to create a new copy of the current node and use that instead. Also, since you'll be ending up with a second list and not altering the original, you should return the new list from reverse.
static struct Node* reverse(const struct Node* head_ref)
{
struct Node* previous = NULL;
const struct Node* current = head_ref;
struct Node* copy;
while (current != NULL) {
copy = malloc(sizeof(*copy));
if (copy == NULL) {
// handle error
}
copy->data = current->data;
copy->next = previous;
previous = copy;
current = current->next;
}
return previous;
}
You can also make the loop prettier by converting it to a for loop.
for (current = head_ref; current != NULL; current = current->next) {
Finally, when you print out the list, you're using %d in the printf format string. %d will print the char as an integer. To print out the actual character, use %c instead.

Linked List elements not getting displayed

This is my program in C which always inserts into a linked list at the end. But when I try to print the list elements, nothing is displayed. Here is the code :
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void insert(struct Node *, int);
int main(void)
{
struct Node *head = NULL, *current;
int n, i, x, data;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(head, data);
}
current = head;
while(current != NULL)
{
printf("%d ", current->data);
current = current->next;
}
}
void insert(struct Node *head, int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
I cannot understand what might be the issue. Please help.
Your insert cannot modify head. Change it to
void insert(struct Node **head, int data)
and change it by
*head = newnode;
and call it like this
insert(&head, data);
Here, while you are passing the head pointer to your insert() function, it is not being updated in your main() function.
So, either declare your head pointer as global or return your head pointer and update it in your main() function.
In the below code I had taken the head pointer as global and removed the head pointer as your parameter from the insert() function.
Here is the code :-
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *head=NULL;
void insert(int);
int main(void)
{
struct Node *current;
int n, i, x, data;
clrscr();
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(data);
}
current = head;
while(current != NULL)
{
printf("%d \n", current->data);
current = current->next;
}
getch();
return 0;
}
void insert(int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the reference of the head pointer, then only the changes made to it will be visible.
You must declare your function like
void insert(struct Node **, int);
and also call it like
insert(&head, data);
also, make changes to function definition
void insert(struct Node **head, int data)
{
struct Node *newnode, *current = *head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(*head == NULL)
{
*head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the head by reference as you are making changes to it that should be visible.
insert(head, data);
should become
insert(&head, data);
Also the function signature will change.
void insert(struct Node *head, int data)
should become
void insert(struct Node **head, int data)
Also make appropriate changes in the function.
Like,
current = *head;
Because you are passing the pointer by value. The function operates on a copy of the pointer, and never modifies the original.
Either pass a pointer to the pointer (i.e. a struct head **), or instead have the function return the pointer.
You can try running the following code which will give the output as null
printf("%s",head);
while(current != NULL)
{
printf("%d", current->data);
current = current->next;
}

Linked List K Alternate Reverse Program

Can Anyone Explain me why the function *kAltReverse return node type prev and how it will work when you call node->next in print function to get the next element from the struct node & print and how it points to next data?
I don't understand how the data is printed using just prev in *kAltReverse function?
Help is very very highly appreciated!!!
Question Source: GeeksforGeeks
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node* next; };
struct node *kAltReverse(struct node *head, int k) {
struct node* current = head;
struct node* next;
struct node* prev = NULL;
int count = 0;
while (current != NULL && count < k)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
count++;
}
if(head != NULL)
head->next = current;
count = 0;
while(count < k-1 && current != NULL )
{
current = current->next;
count++;
}
if(current != NULL)
current->next = kAltReverse(current->next, k);
return prev;
}
void push(struct node** head_ref, int new_data) {
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printList(struct node *node) {
int count = 0;
while(node != NULL)
{
printf("%d ", node->data);
node = node->next;
count++;
}
}
int main(void) {
struct node* head = NULL;
for(int i = 20; i > 0; i--)
push(&head, i);
printf("\n Given linked list \n");
printList(head);
head = kAltReverse(head, 3);
printf("\n Modified Linked list \n");
printList(head);
getchar();
return(0);
}
Looks like there is a problem with int count = 0;.
It should be static int count = 0;, otherwise it would not behave as expected.
This reverses 1st 'k' elements of the linked list using recursion. Its like in 1st iteration of the loop, the 1st element will be placed at Kth position and 2nd element at 1st position, and in next iteration, with k reduced by 1, it will placed the 2nd value(the current 1st value after iteration) to the (k-1)th position (last position for current iteration). This goes on till count reaches to 'k'.

Segmentation fault (core dumped) in Linked List using C

I want an array of linked List and obviously each linked should have separate head node. Initially, as an example, I am starting with one array element. I am storing linkedlist into current[0] . But it is giving segmentation fault. If I use Node *current it will create a list and working fine. But, I want to store the list within array. What is wrong with the code ?
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
Node *current[20];
void insert_beg_of_list(Node *current[0], int data);
void print_list(Node *current[0]);
void insert_beg_of_list(Node *current[0], int data) {
//keep track of first node
Node *head = current[0];
while(current[0]->next != head) {
current[0] = current[0]->next;
}
current[0]->next = (Node*)malloc(sizeof(Node));
current[0] = current[0]->next;
current[0]->data = data;
current[0]->next = head;
}
void print_list(Node *current[0]) {
Node *head = current[0];
current[0] = current[0]->next;
while(current[0] != head){
printf(" %d ", current[0]->data);
current[0] = current[0]->next;
}
}
int main() {
Node *head = (Node *)malloc(sizeof(Node));
head->next = head;
int data = 0 ;
int usr_input = 0;
int i;
int m;
int j;
scanf("%d", &usr_input);
for (i=0; i<usr_input; i++) {
scanf("%d", &data);
insert_beg_of_list(head, data);
}
printf("The list is ");
print_list(head);
printf("\n\n");
return 0;
}
I think you have mixed the global array current's use. Change your code to this :
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
void insert_beg_of_list(Node *current, int data);
void print_list(Node *current);
void insert_beg_of_list(Node *current, int data) {
//keep track of first node
Node *head = current;
while(current->next != head) {
current = current[0]->next;
}
current->next = malloc(sizeof(Node));
if (current->next == NULL)
return;
current = current->next;
current->data = data;
current->next = head;
}
void print_list(Node *current) {
Node *head = current;
current = current->next;
while(current != head){
printf(" %d ", current->data);
current = current->next;
}
}
int main() {
Node *current[20];
Node *head = malloc(sizeof(Node));
if (head == NULL)
return;
head->next = head;
int data = 0 ;
int usr_input = 0;
int i;
int m;
int j;
scanf("%d", &usr_input);
for (i = 0; i < usr_input; i++) {
scanf("%d", &data);
insert_beg_of_list(head, data);
}
//assign the newly created pointer to a place in the array
current[0] = head;
printf("The list is ");
print_list(head);
printf("\n\n");
return 0;
}
Keep in mind that the parameter current in your functions' prototypes and declarations is not the same as the array current created in your main function. I just left the name as it was.
NOTE : You should do something with head->next pointer, initialize it.
Also read this link on why not to cast the result of malloc and another one on why you should check its result.
You probably want this:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
void insert_beg_of_list(Node *current, int data);
void print_list(Node *current);
void insert_beg_of_list(Node *current, int data) {
//keep track of first node
Node *head = current;
while (current->next != head) {
current = current->next;
}
current->next = (Node*)malloc(sizeof(Node));
current = current->next;
current->data = data;
current->next = head;
}
void print_list(Node *current) {
Node *head = current;
current = current->next;
while (current != head) {
printf(" %d ", current->data);
current = current->next;
}
}
Node *NewList()
{
Node *newnode = (Node *)malloc(sizeof(Node));
newnode->next = newnode;
}
int main() {
Node *arrayofheads[20];
// We are using only arrayofheads[0] in this example
arrayofheads[0] = NewList();
int data = 0;
int usr_input = 0;
int i;
scanf("%d", &usr_input);
for (i = 0; i<usr_input; i++) {
scanf("%d", &data);
insert_beg_of_list(arrayofheads[0], data);
}
printf("The list is ");
print_list(arrayofheads[0]); printf("\n\n");
return 0;
}

output linked list to txt file

Hello I am trying to export a linked list to a text file but somehow all the time the text file reaches to very big size(5gb)and not opened.
I would be happy if you could see what the problem is and offer me a way to repair her thanks
My code -
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node;
node* insert(node* head, int num);
void free_list(node *head);
void fprintfList(node *head);
int main()
{
int num;
int temp;
node *head, *p;
head = NULL;
FILE * MyFile;
do
{
printf("Enter numbers\n");
scanf("%d",&num);
if(num)
{
head = insert(head, num);
}
} while(num);
p = head;
MyFile = fopen("New_File.txt","w");
while(head)
{
fprintf(MyFile, "%d\n",head->next);
}
//fprintfList(head);
free_list(head);
fclose(MyFile);
return 0;
}
node* insert(node* head, int num)
{
node *temp, *prev, *next;
temp = (node*)malloc(sizeof(node));
temp->data = num;
temp->next = NULL;
if(!head){
head=temp;
} else{
prev = NULL;
next = head;
while(next && next->data<=num){
prev = next;
next = next->next;
}
if(!next){
prev->next = temp;
} else{
if(prev) {
temp->next = prev->next;
prev-> next = temp;
} else {
temp->next = head;
head = temp;
}
}
}
return head;
}
void free_list(node *head)
{
node *prev = head;
node *cur = head;
while(cur)
{
prev = cur;
cur = prev->next;
free(prev);
}
}
while(head)
{
fprintf(MyFile, "%d\n",head->next);
}
Your problem lies here. You loop until head is NULL, but never actually change the head pointer, hence you'll just loop forever writing the same data out until you run out of disk space. In addition, you're printing the value of the next pointer, not actually the data stored in the node.
You first need print the actual data, so change the fprintf to:
fprintf(MyFile, "%d\n",head->data);
Secondly, you actually need to iterate over the list, like follows
while(head)
{
fprintf(MyFile, "%d\n",head->data);
head = head->next;
}

Resources