can't get response from a function in c [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm writing a program that creates a doubly linked list and removes a element with negative value from it. Everything pretty much works, except for the part when I called the modify function and when I try to delete it, program crashes. Any suggestions?
/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#include<stdio.h>
#include<stdlib.h>
struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int);
void modify(struct list*);
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the count of node :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("\nDoubly linked list is created and the list is as follows : \n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
struct list* create(int value) {
struct list *new_node, *temp;
temp = head;
new_node = (struct list*)malloc(sizeof(struct list));
new_node -> data = value;
new_node -> next = NULL;
new_node -> prev = NULL;
if (head == NULL) {
head = new_node;
}
else {
while (temp -> next != NULL) {
temp = temp -> next;
}
temp -> next = new_node;
new_node -> prev = temp;
}
return head;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
current_node = temp;
prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
next_node -> prev = prev_node;
free(current_node);
}
}
printf("\nThe modified doubly linked list is : \n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}

See the examples of Vlad from Moscow to have a better understanding of what you were doing.
I shall go trough your code and tell you what I would change.
/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
First of all: you're making a (doubly linked) list of nodes, not a list of lists. Call it a Node. Also, you can do a typedef to prevent you from writing struct Node all the time.
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void append(struct Node** head, int value); // variable names aren't needed here
struct Node* findLastNode(struct Node** head);
void removeNegativeNodes(struct Node** head);
void removeNode(struct Node** head, struct Node* currNode);
int main(void)
{
Try not to use global variables. There are many reasons to be found why not to use them, but in here it's possible to don't use them as well. Imagine having thousands of lines of code, you won't be able to have a decent view on the code.
struct Node* head = NULL;
struct Node* p; // temp-<p>ointer
int n, value;
printf("Enter the count of node :");
scanf("%d", &n);
You only need i in the for-loop, so keep it there.
for (int i = 0; i < n; ++i) {
printf("Enter the value of node: ");
scanf("%d", &value);
Make sure your function names are clear and tell you what they do. create() would tell me it creates a Node, but not that it also appends the node.
append(&head, value);
}
// this can be in a function! (A) printData
p = head; // temp-<p>ointer
printf("\nDoubly linked list is created and the list is as follows : \n");
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULL\n");
Look at what you're doing: perhaps you want to make a general function to split the code? Here you're again going trough the list and printing out it's data members.
// this can be in a function! (B) printData
removeNegativeNodes(&head);
printf("\nThe modified doubly linked list is : \n");
p = head;
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULL\n");
}
struct Node* findLastNode(struct Node** head)
{
struct Node* p = *head;
if (p != NULL)
while (p->next != NULL)
p = p->next;
return p;
}
Since your head has to be changed, you'll have to pass the address of the head as well. Also, split your code a bit, so it's easier for yourself to have an idea of your code's structure. If your function is 40 rules long, it will take longer to find out where the cause of the bug is located (exactly).
void append(struct Node** head, int value)
{
struct Node* lastNode = findLastNode(head);
struct Node* nextNode = (struct Node*)malloc(sizeof(struct Node));
if (lastNode != NULL) {
lastNode->next = nextNode;
nextNode->prev = lastNode;
}
else {
*head = nextNode;
nextNode->prev = NULL;
}
nextNode->next = NULL;
nextNode->data = value;
}
Here as well: the first number can be negative, so make sure you can access the head variable by it's address. Also, again keep it simple and split your code in functions removeNegativeNodes > removeNode.
void removeNegativeNodes(struct Node** head)
{
struct Node* p = *head;
struct Node* temp;
while (p != NULL) {
temp = p->next;
if (p->data < 0)
removeNode(head, p);
p = temp;
}
}
void removeNode(struct Node** head, struct Node* currNode)
{
if (currNode->next != NULL)
currNode->next->prev = currNode->prev;
if (currNode->prev != NULL)
currNode->prev->next = currNode->next;
else
*head = currNode->next;
free(currNode);
}
I've tested the code and it should work. Having it worked properly is not important though, it's understanding what happens. I recommend you having a closer look to it. Goodluck!

Your definition of a doubly-linked list does not make great sense.
The list should contain two pointers: to the head node and to the tail node of the list.
So you need to define two structures. The first one defines the node and the second one defines the list itself.
In this case you need not to traverse the whole list to append a new node to the tail of the list.
The function create with the confusing name is based on the global variable head while the function modify instead gets the variable through a parameter.
This is very confusing. As result for example you can not create two lists in a program.
So as the function modify gets the pointer to the head node by value then it means that it deals with a copy of the pointer to the head node. As a result any changes of the pointer to the head node in the function does not influence on the original pointer to the head node.
This loop in the function modify
temp = head;
while (temp -> next != NULL) {
in general can invoke undefined behavior because it is not excluded that the pointer to the head node can be equal to NULL.
And in any case the condition of the loop does not make sense because within the loop you are considering not the next node but the current
while (temp -> next != NULL) {
if (temp -> data < 0) {
So a question arises if temp->next is equal to NULL but the value of the current node pointed to by the pointer temp is negative does it mean that this node will not be removed?
Pay attention to that if you will write the condition of the loop correctly nevertheless either data member prev of the removed node or the data member next of the removed node or even the both can be equal to NULL. In this case these statements
prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
^^^^^^^^^^^^^^^^^
next_node -> prev = prev_node;
^^^^^^^^^^^^^^^^^
again can invoke undefined behavior.
here is a demonstrative program that shows how the list and its functions can be defined. Investigate it.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
struct Node *prev;
};
struct List
{
struct Node *head;
struct Node *tail;
};
int push_back( struct List *list, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( list->head == NULL )
{
new_node->prev = NULL;
list->head = list->tail = new_node;
}
else
{
new_node->prev = list->tail;
list->tail = list->tail->next = new_node;
}
}
return success;
}
void remove_if( struct List *list, int predicate( int ) )
{
struct Node *prev = NULL;
for ( struct Node **current = &list->head; *current != NULL; )
{
if ( predicate( ( *current )->data ) )
{
struct Node *tmp = *current;
if ( ( *current )->next != NULL )
{
( *current )->next->prev = ( *current )->prev;
}
*current = ( *current )->next;
free( tmp );
}
else
{
prev = *current;
current = &( *current )->next;
}
}
list->tail = prev;
}
void display( const struct List *list )
{
for ( const struct Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
void display_reverse( const struct List *list )
{
for ( const struct Node *current = list->tail; current != NULL; current = current->prev )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int is_negative( int data )
{
return data < 0;
}
int main(void)
{
struct List list = { .head = NULL, .tail = NULL };
const size_t N = 10;
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
push_back( &list, rand() % N - N / 2 );
}
display( &list );
display_reverse( &list );
putchar( '\n' );
remove_if( &list, is_negative );
display( &list );
display_reverse( &list );
putchar( '\n' );
return 0;
}
The program output might look like
2 -> 4 -> 3 -> -5 -> 3 -> -3 -> -3 -> -2 -> 0 -> 2 -> null
2 -> 0 -> -2 -> -3 -> -3 -> 3 -> -5 -> 3 -> 4 -> 2 -> null
2 -> 4 -> 3 -> 3 -> 0 -> 2 -> null
2 -> 0 -> 3 -> 3 -> 4 -> 2 -> null

The create() function returns a linked list item. so you have to assign the return value to an item. Also the definition of pointers inside the struct is completely wrong.
struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int); //function prototype
void modify(struct list*);//function prototype
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the number of nodes :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("\nDoubly linked list is created and the list is as follows : \n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
void create(int value) {
struct list* point = head;
while(point->next){
if(point->data != value)
point = point->next;
else{
printf("Data exists\n");
return NULL;
}
}
struct list* item = (struct list*)malloc(sizeof(struct list));
item->data = value;
item->next = NULL;
item->prev = point;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
}
temp = temp->next;
}
printf("\nThe modified doubly linked list is : \n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}
I hope this will work for you.

Related

linked list problem when displaying the list in C

having segmentation error while trying to access nodes
i can create new nodes with my add function after function executes i cant access my nodes. i think they deallocated in memory but i couldnt figure it out.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *nextNode;
};
struct node *head;
void add(int data)
{
struct node *new = (struct node *)malloc(sizeof(struct node));
new->data = data;
new->nextNode = NULL;
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
printf("\nValue of temp1:%d\nValue of new: %d\n",temp1,new);
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
void printList()
{
int i = 1;
struct node *tempP;
tempP = head;
while (tempP != NULL)
{
printf("\nData of %dth element is : %d\n", i, tempP->data);
tempP = tempP->nextNode;
i++;
}
}
void main()
{
head = (struct node *)malloc(sizeof(struct node));
head->data = 10;
head->nextNode = NULL;
add(20);
add(30);
add(40);
printList();
}
This code snippet within the function add
struct node *temp1;
temp1 = head;
while (temp1 != NULL)
{
temp1 = temp1->nextNode;
}
temp1 = new;
is wrong. Within it there is changed the local variable temp1. It is not linked with the list.
Also using the conversion specifier %d to output a pointer invokes undefined behavior. You should use conversion specifier %p.
Using your approach to the function definition you could write instead.
void add(int data)
{
struct node *new = malloc( sizeof( *new ) );
new->data = data;
new->nextNode = NULL;
if ( head == NULL )
{
head = new;
}
else
{
struct node *temp1 = head;
while ( temp1->nextNode != NULL)
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new;
}
printf("\nValue of temp1->nextNode:%p\nValue of new: %p\n",
( void * )temp1->nextNode, ( void * )new);
printf("\nData of temp1->nectNode:%d\nData of new:%d\n",
temp1->nextNode->data,new->data);
}
Pay attention to that it is a bad design when functions depend on a global variable as in your case where the functions depend on the global variable head.
And it is also a bad idea when the first node is added to the list bypassing the function add.
And you need check whether a node was successfully allocated.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )
As for me I would declare the pointer to the head node in main like
int main( void )
{
struct node *head = NULL;
// ...
And the function add will look like
int add( struct node **head, int data )
{
struct node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->nextNode = NULL;
while ( *head != NULL ) head = &( *head )->nextNode;
*head = new_node;
}
return success;
}
and called like
struct node *head = NULL;
add( &head, 10 );
add( &head, 20 );
add( &head, 30 );
add( &head, 40 );
In turn the function printList can look like
void printList( const struct node *head )
{
for ( size_t i = 1; head != NULL; head = head->nextNode )
{
printf( "Data of %zuth element is : %d\n", i++, head->data);
}
}
And you need at least to write one more function that will free all the allocated memory.
There were a handful of mistakes in your add() function, which I've highlighted and fixed below:
void add(int data)
{
struct node *new = malloc(sizeof(*new)); // suggested by ryyker
new->data = data;
new->nextNode = NULL;
struct node *temp1 = head; // just keep it short
while (temp1->nextNode != NULL) // temp1 != NULL will always result in it being NULL, last node is the node with NULL as next
{
temp1 = temp1->nextNode;
}
temp1->nextNode = new; // you want the next in the list to be the new node, not reassign the head to a new node. That's a memory leak.
// remember: temp1 == head, and head = new makes head lose the original node and point to the newly created one
printf("\nValue of temp1:%p\nValue of new: %p\n",temp1,new); // %p for pointers
printf("\nData of temp1:%d\nData of new:%d\n",temp1->data,new->data);
}
Output:
Value of temp1:0x55809a4b22a0
Value of new: 0x55809a4b22c0
Data of temp1:10
Data of new:20
Value of temp1:0x55809a4b22c0
Value of new: 0x55809a4b26f0
Data of temp1:20
Data of new:30
Value of temp1:0x55809a4b26f0
Value of new: 0x55809a4b2710
Data of temp1:30
Data of new:40
Data of 1th element is : 10
Data of 2th element is : 20
Data of 3th element is : 30
Data of 4th element is : 40

Reversing a linked list list

I was trying to reverse a linked list but I kept comming across an issue. I finally figured out was wrong and fixed it, however I do not understand why my last approach doesn't work. The code below is the one that successfully reverses a linked list.
void reverse_list(list** head)
{
list* currNode = *head;
list* prevNode = NULL;
list* tmpNode;
while(1)
{
tmpNode = currNode->next;
currNode->next = prevNode;
if(tmpNode == NULL)
{
*head = currNode;
break;
}
prevNode = currNode;
currNode = tmpNode;
}
}
However, the code below does not work. Both use double pointers, but in this one I dereferenced head twice to get to the actual object and assigned it with *currNode. When I run this code, It ends up going into an infinite loop and its missing the last item. For example, if the items were 1,2,3,4,5, then the reverse would be 5,4,3,2, and it keeps printing the same list. I don't understand why this approach isn't working since I'm accessing the actual object (by derefrening twice) and assigning it with a new object (*currNode).
void reverse_list(list** head)
{
list* currNode = *head;
list* prevNode = NULL;
list* tmpNode;
while(1)
{
tmpNode = currNode->next;
currNode->next = prevNode;
if(tmpNode == NULL)
{
**head = *currNode;
break;
}
prevNode = currNode;
currNode = tmpNode;
}
}
The code below has the same issue as the one above. I followed the same approach as with the above code only this one uses a single pointer.
void reverse_list(list* head)
{
list* currNode = head;
list* prevNode = NULL;
list* tmpNode;
while(1)
{
tmpNode = currNode->next;
currNode->next = prevNode;
if(tmpNode == NULL)
{
*head = *currNode;
break;
}
prevNode = currNode;
currNode = tmpNode;
}
}
Any help to understand this would greatly be appreciated. Thank you!
Different levels of indirection.
Given list** head, *head is the value pointed to by head, a pointer to a Node, a list *. We dereference one more time and **head dereferences to list * and then to list. We're all out of pointers and and are accessing the object at the end of the line. So
**head = *currNode;
dereferences both pointers all the way back to the objects. This is assigning values to objects, not addresses to pointers to objects. Rather than changing the linkage of the list by updating pointers, whatever list head ultimately pointed at has been changed to match currNode, breaking the integrity of the list.
*head = currNode;
only derefences head one level closer to the object. Here we are operating on pointers and changing linkage.
In the final example we have
*head = *currNode;
and this is similar to the first failed attempt. It is assigning values rather than changing the pointers.
For starters all the three functions in general can invoke undefined behavior when they are called for empty lists due to these lines
list* currNode = head;
//...
tmpNode = currNode->next;
because there is used a null pointer to access memory.
In the second function in this if statement
if(tmpNode == NULL)
{
**head = *currNode;
break;
}
the original first node is overwritten by the last node
**head = *currNode;
So after exiting the function you will have that the original pointer head still points to the originally first node that was overwritten by the last node of the list. So as a result one actual data will be lost and there will be a memory leak.
As for the third function then it is enough to point to that the function accepts the pointer to the head node by value.
void reverse_list(list* head)
That is the function deals with a copy of the value of the original variable head. Changing the copy will not influence on the original pointer. The original pointer will still point to the first node.
The function can look simpler the following way
void reverse( list **head )
{
list *current = *head;
*head = NULL;
while ( current != NULL )
{
struct Node *tmp = current;
current = current->next;
tmp->next = *head;
*head = tmp;
}
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
} list;
int push_front( list **head, int data )
{
list *new_node = malloc( sizeof( list ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void display( const list *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void reverse( list **head )
{
list *current = *head;
*head = NULL;
while ( current != NULL )
{
list *tmp = current;
current = current->next;
tmp->next = *head;
*head = tmp;
}
}
int main(void)
{
const int N = 10;
list *head = NULL;
display( head );
reverse( &head );
display( head );
putchar( '\n' );
for ( int i = 0; i < N; i++ )
{
push_front( &head, i );
}
display( head );
reverse( &head );
display( head );
return 0;
}
The program output is
null
null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

Why isn't my reverse(); function working?

I'm writing a program in C for reversing a circular singly linked list. I keep getting segmentation fault for some reason. I'm sure the problem is with the reverse function as I tried commenting the function call, the program works fine.
For my reverse() function, I have used 3 pointers: prev, next and curr. The logic is that I'll run a loop till curr takes the address of head, which will be stored in the link part of the last node since it is a circular linked list. I'll keep updating curr->link using prev pointer which will change its link from the next to its previous node.
When the loop breaks, head->link = prev; and head = prev; will update the respective addresses such that they point to the first node of the reversed list.
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
The loop in the reverse() function exits immediately because curr is initialized to the value of head so the test while (curr != head) is false at the first iteration.
reverse() then sets head->link to NULL and finally head is also set to NULL (the initial value of prev), which explains the segmentation fault in the subsequent disp() function where you use a do { } while (pre != head) that cannot handle an empty list.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}
For starters it is a bad idea to use the global variable head
struct node {
int data;
struct node *link;
} *head;
In this case the functions depend on the global variable and you can not use more than one list in a program.
Due to this initialization
struct node *prev = NULL, *curr = head, *next;
^^^^^^^^^^^^
the condition of the while loop
while (curr != head) {
is never evaluates to true because initially the pointer curr is equal to the pointer head.
Moreover if the list is empty then this statement
head->link = prev;
invokes undefined behavior.
Here is a demonstrative program that shows how the list can be declared in main and then reversed.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *link;
};
size_t assign( struct node **head, const int a[], size_t n )
{
while ( *head )
{
struct node *tmp = *head;
*head = ( *head )->link;
free( tmp );
}
size_t total = 0;
struct node *first = NULL;
while ( total < n && ( *head = malloc( sizeof( struct node ) ) ) != NULL )
{
( *head )->data = a[total];
( *head )->link = NULL;
++total;
if ( first == NULL ) first = *head;
head = &( *head )->link;
}
if ( first != NULL ) *head = first;
return total;
}
void display( const struct node *head )
{
if ( head != NULL )
{
const struct node *current = head;
do
{
printf( "%d -> ", current->data );
} while ( ( current = current->link ) != head );
}
puts( "null" );
}
struct node * reverse( struct node **head )
{
if ( *head )
{
struct node *last = *head;
struct node *prev = NULL;
while ( ( *head )->link != last )
{
struct node *current = *head;
*head = ( *head )->link;
current->link = prev;
prev = current;
}
( *head )->link = prev;
last->link = *head;
}
return *head;
}
int main(void)
{
struct node *head = NULL;
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
display( head );
display( reverse( &head ) );
display( reverse( &head ) );
return 0;
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

How can I insert a node in a singly linked list using recursion given: 1. a pointer to the head node 2. the index to insert the new node

The function below is the one I am trying to work on. The problem I am running into is that I do not know how to "keep" the pointer to the original head to the list as that is what I have to return after insertion.
There is no Driver code so everything must be done inside this function.
Because I must do this recursively I cannot just create a temporary node to point to the original head. I am just getting used to recursion and I cannot find a solution.
NOTE: There are some other problems with my function as I believe it wouldn't work well for inserting a new node into the beginning and end of the linked list but I am confident I could work out those edge cases.
The main thing I am trying to learn is how to "store" the original head of my list.
All help is appreciated.
Node* insert(Node* head, int index, int data)
{
if (head == NULL) return NULL; // if list is empty
if (index == 1) // if we have accessed node before insertion
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->next = head->next; // new_node->next now links to the node next in the list
head->next = new_node; // head->next links to new node
new_node->data = data; // assigns new node its data
return head; // not sure how to return original head
}
return insert(head->next, index - 1, data);
}
Node *insertRecursive(Node* head,int pos,int val)
{
if(pos==0 || head==NULL)
{
Node *newNode= new Node(val);
newNode->next=head;
head=newNode;
return head;
}
else
head->next = insertRecursive(head->next,pos-1,val);
}
For starters the parameter that specifies the position where a node has to be inserted should have an unsigned integer type, for example, size_t. Positions should start from 0.
The function can be defined the following way
struct Node * insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0 )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
new_node->next = head;
new_node->data = data;
head = new_node;
}
else
{
head->next = insert( head->next, pos - 1, data );
}
return head;
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node * insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0)
{
struct Node *new_node = malloc( sizeof( struct Node ) );
new_node->next = head;
new_node->data = data;
head = new_node;
}
else
{
head->next = insert( head->next, pos - 1, data );
}
return head;
}
void print( const struct Node *head )
{
for (; head != NULL; head = head->next)
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main( void )
{
struct Node *head = NULL;
head = insert( head, 0, 3 );
print( head );
head = insert( head, 0, 0 );
print( head );
head = insert( head, 1, 1 );
print( head );
head = insert( head, 2, 2 );
print( head );
}
The program output is
3 -> null
0 -> 3 -> null
0 -> 1 -> 3 -> null
0 -> 1 -> 2 -> 3 -> null
Node* insert_Node_recursively(Node* head,int data,int position){
//Inserting on the first node.
if(position==0){
Node* newNode=new Node(data);
newNode->next=head;
head=newNode;
return head;
}
if((head->next==NULL && position==0) /*for adding on the end of the list */ || position==1 /*Inserting on node in between */){
Node* newNode=new Node(data);
newNode->next=head->next;
head->next=newNode;
return head;
}
//in case the position exceeds the total number of nodes
if(head->next==NULL && position>0){
return head;
}
else{
head->next=insert_Node_recursively(head->next,data,position-1);
}
return head;
}
this will work I think, covered all the aspects
//if you have created a node using class then here is the solution
//to insert a node at a position recurssively
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//here is the full solution to add a node recursively at a position
#include<iostream>
using namespace std;
//the below code is for creation of class for node
class Node
{
public:
int data;
Node * next;
Node(int data) //constructor
{
this -> data = data;
next = NULL;
}
};
//the below code is for creation of linked list
//a terminator -1 is used to stop taking input
Node * takeInput()
{
int data;
cout<<"Enter the data of the node to be inserted ( use -1 to terminate
the insertion ) : ";
cin>>data;
Node * head = NULL;
Node * tail = NULL;
while(data != -1)
{
Node * newNode = new Node(data);
if(head == NULL)
{
head = newNode;
tail = newNode;
}
else
{
tail->next=newNode;
tail = tail -> next;
}
cout<<"Enter the data of the node to be inserted ( use -1 to
terminate the insertion ) : ";
cin>>data;
}
return head;
}
//the below code is to print the linked list
void print(Node * head)
{
if(head == NULL)
{
cout<<"The linked list id empty !"<<endl;
return;
}
Node * temp = head;
while(temp != NULL)
{
cout<<temp->data<<" ";
temp = temp -> next;
}
cout<<endl;
}
//the below part is the main solution to the problem
//insertion at a position using recursion
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//this is the main from where all the function calls happen
int main()
{
int data, key;
Node * head = takeInput();
print(head);
cout<<"Enter the data of the node to be inserted : ";
cin>>data;
cout<<"Enter the position of insertion : ";
cin>>key;
head = insertRecursive(head,data,key);
print(head);
}

Delete last two elements from linked list in C

I have this piece of code, it deletes the last element from a linked list. What changes do I have to make so it will delete the last TWO elements of the linked list?
void deletesEnd() {
struct node *temp, *last;
temp = head;
last = temp;
while (temp != NULL && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == temp) {
free(temp);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
}
The simplest solution to remove the last 2 elements of the list is to call deletesEnd() twice. Note that deletesEnd() should take head as an argument and return the new value. You would delete the last 2 by issuing a nested call:
struct node *deletesEnd(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
free(head);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
return head;
}
Delete the last element: head = deletesEnd(head);
Delete the last 2 elements: head = deletesEnd(deletesEnd(head));
The simplicity of the design more than compensates for the overhead of enumerating the list twice.
If you absolutely want a specific function, you can extend your approach this way:
struct node *deleteLast2Nodes(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL && temp->next->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
if (head) {
free(head->next);
}
free(head);
head = NULL;
} else {
free(last->next->next);
free(last->next);
last->next = NULL;
}
return head;
}
Here is a demonstrative program that shows how two last nodes can be deleted simultaneously. In fact the function is similar to your function except it checks not only the next node but also the next->next node.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
struct node *next;
} *head;
void push( int value )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->value = value;
tmp->next = head;
head = tmp;
}
void display()
{
for ( struct node *current = head; current; current = current->next )
{
printf( "%d ", current->value );
}
}
void deleteLastTwo()
{
struct node *current = head;
struct node *prev = head;
if ( current && current->next )
{
while ( current->next->next )
{
prev = current;
current = current->next;
}
}
if ( current )
{
if ( current->next )
{
free( current->next );
}
if ( prev == current )
{
head = NULL;
}
else
{
prev->next = NULL;
}
free( current );
}
}
int main(void)
{
const int N = 11;
for ( int i = N; i != 0; i-- ) push( i - 1 );
display();
printf( "\n" );
while ( head )
{
deleteLastTwo();
display();
printf( "\n" );
}
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6
0 1 2 3 4
0 1 2
0
Take into account that it is not a good idea when the head node is declared like a global variable. It is better when it can be declared like a local variable. In this case you will need to rewrite the methods of the list because in most cases the current methods will not work correctly.
This logic will delete your last 2 node in singly linked list.
void deletesEnd()
{
struct node *temp, *last;
temp = head;
last = temp;
while (temp->next->next != NULL)
{
last = temp->next;
if(last->next->next!=NULL)
temp = temp->next;
else
break;
}
struct node *ptr=last->next;
last->next=ptr->next;
free(ptr);
temp->next=last->next;
free(last);
}
For fun & education: simple recursive version.
The function return := the number of nodes below us
After the recursion returns, we can decide if we are too close to the tail.
and remove ourselves
because we pass a pointer to pointer, this should also work for lists of size=2 and smaller
unsigned del_tail_n(struct llist **pp, unsigned nn)
{
unsigned pos;
if (!*pp) return 0;
// this recursive call returns 0 iff (*pp)->next is NULL
pos = del_tail_n( &(*pp)->next, nn);
if (pos < nn) {
// free (*pp);
*pp = NULL;
}
return 1+pos;
}
For those who don't like recursion, here is a non-recursive version.
[do note that both versions work for empty lists (*pp == NULL) , or for lists smaller than nn ]
void del_tail_n2(struct llist **pp, unsigned nn)
{
struct llist *p;
/* Advance p pointer n positions down, starting from *pp. */
for (p= *pp; p; p=p->next) {
if (nn-- < 1) break;
}
/* Do a synchronous walk down for both p and *pp, until p is NULL. */
for ( ; p; p=p->next) {
pp = &(*pp)->next;
}
/* Now, *pp is the first node to delete
** Delete it and everything below it.
*/
for ( ;(p = *pp); ){
*pp = p->next;
// free (p);
}
return;
}

Resources