dequeueing function working with 2 queues encounters segfault? - c

The function below is supposed to dequeue a structure that is made of 2 queues. Each time we dequeue the first queue, its rear needs to become the front of the second queue. Essentially moving the first element in the second queue to the first queue to be its rear. I came up with the algorithm below:
int dequeue(queue* Q1,queue* Q2){
node* temp;
if(Q1->rear=NULL){
return 0;
}
if(count<3){
temp=Q1->front;
Q1->front=Q1->front->next;
free(temp);
count--;
return 1;
}
if(count>=3){
temp=Q1->front;
Q1->front=Q1->front->next;
free(temp);
Q1->rear->next=Q2->front;
Q1->rear=Q1->rear->next;
Q2->front=Q2->front->next;
Q1->rear->next=NULL;
if(Q2->front=NULL){
Q2->rear=NULL;
}
count--;
return 1;
}
}
It gives a segfault at Q1->rear->next=Q2->front;
is there an alternative way to achieve this?

For starters there is a typo in the condition of the if statement
if(Q2->front=NULL){
Q2->rear=NULL;
}
You are using assignment instead of comparison.
There is also a bug in this if statement
if(count<3){
temp=Q1->front;
Q1->front=Q1->front->next;
free(temp);
count--;
return 1;
}
q1-front after this statement
Q1->front=Q1->front->next;
can be equal to NULL. In this case you need to set also Q1->rare to NULL.
But in any case your approach with the if statements
if(count<3){
temp=Q1->front;
Q1->front=Q1->front->next;
free(temp);
count--;
return 1;
}
if(count>=3){
temp=Q1->front;
Q1->front=Q1->front->next;
free(temp);
//...
makes the code less clear and as it occurred error prone.
I would write the function the following way
int dequeue( queue *q1, queue *q2 )
{
int success = q1->front != NULL;
if ( success )
{
if ( q2->front != NULL )
{
q1->rear->next = q2->front;
q1->rear = q1->rear->next;
q2->front = q2->front->next;
if ( q2->front == NULL ) q2->rear = NULL;
q1->rear->next = NULL;
}
node *tmp = q1->front;
q1->front = q1->front->next;
if ( q1->front == NULL ) q1->rear = NULL;
free( tmp );
--count;
}
return success;
}
Pay attention to that it is a bad programming practice when a function depends on a global variable (I mean the variable count). You could avoid such a situation wrapping queues and the variable count in a structure.
Here is a demonstration program that shows the function in action.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct queue
{
node *front;
node *rear;
} queue;
size_t count;
int dequeue( queue *q1, queue *q2 )
{
int success = q1->front != NULL;
if ( success )
{
if ( q2->front != NULL )
{
q1->rear->next = q2->front;
q1->rear = q1->rear->next;
q2->front = q2->front->next;
if ( q2->front == NULL ) q2->rear = NULL;
q1->rear->next = NULL;
}
node *tmp = q1->front;
q1->front = q1->front->next;
if ( q1->front == NULL ) q1->rear = NULL;
free( tmp );
--count;
}
return success;
}
int push( queue *q, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( q->rear == NULL )
{
q->front = new_node;
}
else
{
q->rear->next = new_node;
}
q->rear = new_node;
++count;
}
return success;
}
int empty( const queue *q )
{
return q->front == NULL;
}
int front( queue *q )
{
return q->front->data;
}
int main( void )
{
queue q1 = { .front = NULL, .rear = NULL };
queue q2 = { .front = NULL, .rear = NULL };
const int N = 10;
for ( int i = 0; i < N; i++ )
{
if ( i < N / 2 ) push( &q1, i );
else push( &q2, i );
}
while ( !empty( &q1 ) )
{
printf( "%d ", front( &q1 ) );
dequeue( &q1, &q2 );
}
putchar( '\n' );
for ( int i = 0; i < N; i++ )
{
if ( i < N / 2 ) push( &q1, i );
else push( &q2, i );
}
while ( !empty( &q1 ) )
{
printf( "%d ", front( &q1 ) );
dequeue( &q1, &q2 );
}
putchar( '\n' );
}
The program output is
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
There are the same code is executed two times to show that the function dequeue works correctly.

Related

A C function that inserts number into a linked list in ascending order

This is my function:
void IntListInsertInOrder (IntList L, int v)
{
struct IntListNode *n = newIntListNode (v);
if (L->first == NULL) { //case a, empty list
L->first = L->last = n;
L->size ++;
return;
}
else if (v <= L->first->data) { // case b, smallest value
n->next = L->first;
L->first = n;
}
else if (v >= L->last->data) { // case c, largest value
L->last->next = n;
L->last = n;
}
else if (v > L->first->data && v <= L->first->next->data) { // case d, second-smallest value
n->next = L->first->next;
L->first->next = n;
}
else { //case f, value in the middle
struct IntListNode *curr = L->first;
while (curr->next->data < v) {
curr = curr->next;
}
n->next = curr->next;
curr->next = n;
}
L->size ++;
return;
}
when i put random lists of 10 numbers into it, 3/10 sorted correctly. the errors seem to be in the last part but it looks exactly like solutions i found online.
OK I figured it out. I forgot to add&& curr-> != NULLin the condition of the last while loop. After I added that all the test cases passed.
Your function is too complicated, has many if conditions and as a result it is error-prone and unreadable.
You did not show the list definition but I can guess that you have a two-sided singly-linked list because nowhere in the code there is a reference to a data member named prev.
Here is a demonstrative program that shows how the function can be simply defined.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef struct List
{
Node *head;
Node *tail;
size_t size;
} List;
int insert_in_order( List *list, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
Node **current = &list->head;
while ( *current != NULL && !( data < ( *current )->data ) )
{
current = &( *current )->next;
}
new_node->next = *current;
if ( *current == NULL )
{
list->tail = new_node;
}
*current = new_node;
++list->size;
}
return success;
}
void clear( List *list )
{
while ( list->head != NULL )
{
Node *current = list->head;
list->head = list->head->next;
free( current );
}
}
void display( const List *list )
{
printf( "There are %zu nodes in the list\n", list->size );
printf( "They are: " );
for ( const Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
List list = { .head = NULL, .tail = NULL, .size = 0 };
srand( ( unsigned int )time( NULL ) );
const size_t N = 10;
for ( size_t i = 0; i < N; i++ )
{
insert_in_order( &list, rand() % ( int )N );
}
display( &list );
clear( &list );
return 0;
}
The program output might look like
There are 10 nodes in the list
They are: 1 -> 2 -> 3 -> 3 -> 6 -> 6 -> 7 -> 8 -> 8 -> 9 -> null

How can I return the odd indexed nodes of a singly linked list in a new singly linked list ?Assume index of the first node as 1

When I run this code I am not getting an error message from the compiler but I can not return the new list. Am I writing down the code wrong in the MAIN part?
Input
10->20->30->40->50->60->70->80->90->100
Output must be
10->30->50->70->90
#include <stdio.h>
#include <stdlib.h>
typedef struct SinglyLinkedListItem
{
int data;
struct SinglyLinkedListItem*next;
}SLLI;
SLLI*OddNodes(SLLI*pHead)
{
int counter =1;
SLLI*pTemp=pHead;
SLLI*pList=NULL;
while(pTemp != NULL)
{
if(counter % 2 != 0)
{
if(pList==NULL)
{
pList=malloc(sizeof(SLLI));
pList->data=pTemp->data;
pList->next=NULL;
}
else
{
SLLI*pIter=pList;
SLLI*pNew=malloc(sizeof(SLLI));
pNew->data=pTemp->data;
pNew->next=NULL;
pIter->next=pNew;
pIter=pIter->next;
}
}
pTemp=pTemp->next;
counter ++;
}
return pList;
}
You are always changing the same object pList->next.
else
{
pList->next=pTemp;
}
And moreover the original list is not being changed. So the function has undefined behavior.
For starters you should pass the head of the original node by reference. Otherwise the function will deal with a copy of head and any changes of the copy will not influence on the original list.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <stdlib.h>
typedef struct SinglyLinkedListItem
{
int data;
struct SinglyLinkedListItem *next;
} SLLI;
SLLI * OddNodes( SLLI **pHead )
{
int odd = 0;
SLLI *pList = NULL;
SLLI **pCurrent = &pList;
while ( *pHead != NULL )
{
if ( odd ^= 1 )
{
*pCurrent = *pHead;
*pHead = ( *pHead )->next;
( *pCurrent )->next = NULL;
pCurrent = &( *pCurrent )->next;
}
else
{
pHead = &( *pHead )->next;
}
}
return pList;
}
int insert( SLLI **pHead, int data )
{
SLLI *pCurrent = malloc( sizeof( SLLI ) );
int success = pCurrent != NULL;
if ( success )
{
pCurrent->data = data;
pCurrent->next = *pHead;
*pHead = pCurrent;
}
return success;
}
void out( SLLI *pHead )
{
for ( ; pHead != NULL; pHead = pHead->next )
{
printf( "%d -> ", pHead->data );
}
puts( "null" );
}
int main(void)
{
const int N = 10;
SLLI *pHead = NULL;
for ( int i = N; i != 0; --i )
{
insert( &pHead, 10 * i );
}
out( pHead );
SLLI *pSecondHead = OddNodes( &pHead );
out( pHead );
out( pSecondHead );
return 0;
}
The function output is
10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70 -> 80 -> 90 -> 100 -> null
20 -> 40 -> 60 -> 80 -> 100 -> null
10 -> 30 -> 50 -> 70 -> 90 -> null
If you are not going to change the original list then the function can look simpler because in this case there is no need to pass the pointer pHead to the function by reference.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct SinglyLinkedListItem
{
int data;
struct SinglyLinkedListItem *next;
} SLLI;
SLLI * OddNodes( SLLI *pHead )
{
int odd = 0;
SLLI *pList = NULL;
SLLI **pCurrent = &pList;
for ( ; pHead != NULL; pHead = pHead->next )
{
if ( odd ^= 1 )
{
*pCurrent = malloc( sizeof( SLLI ) );
( *pCurrent )->data = pHead->data;
( *pCurrent )->next = NULL;
pCurrent = &( *pCurrent )->next;
}
}
return pList;
}
int insert( SLLI **pHead, int data )
{
SLLI *pCurrent = malloc( sizeof( SLLI ) );
int success = pCurrent != NULL;
if ( success )
{
pCurrent->data = data;
pCurrent->next = *pHead;
*pHead = pCurrent;
}
return success;
}
void out( SLLI *pHead )
{
for ( ; pHead != NULL; pHead = pHead->next )
{
printf( "%d -> ", pHead->data );
}
puts( "null" );
}
int main(void)
{
const int N = 10;
SLLI *pHead = NULL;
for ( int i = N; i != 0; --i )
{
insert( &pHead, 10 * i );
}
out( pHead );
SLLI *pSecondHead = OddNodes( pHead );
out( pHead );
out( pSecondHead );
return 0;
}
Its output is
10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70 -> 80 -> 90 -> 100 -> null
10 -> 20 -> 30 -> 40 -> 50 -> 60 -> 70 -> 80 -> 90 -> 100 -> null
10 -> 30 -> 50 -> 70 -> 90 -> null
If you do not yest understand the work with pointers by reference then the function can look the following way
SLLI * OddNodes( SLLI *pHead )
{
int odd = 0;
SLLI *pList = NULL;
for ( SLLI *pCurrent = pList; pHead != NULL; pHead = pHead->next )
{
if ( odd ^= 1 )
{
if ( pCurrent == NULL )
{
pList = malloc( sizeof( SLLI ) );
pList->data = pHead->data;
pList->next = NULL;
pCurrent = pList;
}
else
{
pCurrent->next = malloc( sizeof( SLLI ) );
pCurrent->next->data = pHead->data;
pCurrent->next->next = NULL;
pCurrent = pCurrent->next;
}
}
}
return pList;
}

merge two sorted linked list into one linked list (recursion)

I had to write a recursive function that receives two sorted lists:
typedef struct listNode {
int* dataPtr;
struct listNode* next;
} ListNode;
typedef struct list
{
ListNode* head;
ListNode* tail;
} List;
and merge them into one sorted list.
I wrote these functions:
void mergeRec(ListNode* head1, ListNode* head2, ListNode* mergedList)
{
if (head1 == NULL && head2 == NULL)
return;
else if (head1 == NULL) {
mergedList->next = head2;
head2 = head2->next;
}
else if (head2 == NULL) {
mergedList->next = head1;
head1 = head1->next;
}
else if (*(head1->dataPtr) > *(head2->dataPtr)) {
mergedList->next = head1;
head1 = head1->next;
}
else
{
mergedList->next = head2;
head2 = head2->next;
}
mergeRec(head1, head2, mergedList->next);
}
List merge(List lst1, List lst2)
{
List mergedList;
makeEmptyList(&mergedList);
mergeRec(lst1.head, lst2.head, mergedList.head);
return mergedList;
}
Now, the problem I have with the recursive function is that at the first call when merged list is pointing to null, so obviously when I write something like mergeList->next I will get a running bug.
I tried to solve it by adding the following condition in the recursion:
if (mergedList == NULL)
{
if (*(head1->dataPtr) > *(head2->dataPtr))
{
mergedList = head1;
head1 = head1->next;
}
else
{
mergedList = head2;
head2 = head2->next;
}
}
but I got this error:
"Exception thrown at 0x00661EB9 in q2d.exe: 0xC0000005: Access violation writing location 0x01000F48."
I can't tell the problem, or how do I solve it.
I would very much appreciate your help.
Thanks!
For starters it is entirely unclear why in this structure there is a data member of type int *
typedef struct listNode {
int* dataPtr;
struct listNode* next;
}List;
instead of just of type int
typedef struct listNode {
int data;
struct listNode* next;
}List;
Nevertheless, the functions merge and mergeRec are invalid because they deal with copies of values of lists and of pointers list1.head, list2.head, and mergedList.head.
List merge(List lst1, List lst2)
mergeRec(lst1.head, lst2.head, mergedList.head);
Moreover the pointers list1.tail, list2.tail, and mergedList.tail are ignored.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct listNode
{
int *dataPtr;
struct listNode *next;
} ListNode;
typedef struct list
{
ListNode *head;
ListNode *tail;
} List;
void makeEmpty( List *list )
{
list->head = list->tail = NULL;
}
int push( List *list, int data )
{
ListNode *current = malloc( sizeof( ListNode ) );
int success = current != NULL;
if ( success )
{
current->dataPtr = malloc( sizeof( int ) );
success = current->dataPtr != NULL;
if ( success )
{
*current->dataPtr = data;
current->next = NULL;
if ( list->head == NULL )
{
list->head = list->tail = current;
}
else
{
list->tail = list->tail->next = current;
}
}
else
{
free( current );
current = NULL;
}
}
return success;
}
List merge( List *first, List *second )
{
List result;
makeEmpty( &result );
if ( ( second->head != NULL ) &&
( first->head == NULL || *second->head->dataPtr < *first->head->dataPtr ) )
{
result.head = result.tail = second->head;
second->head = second->head->next;
if ( second->head == NULL ) second->tail = NULL;
}
else if ( first->head != NULL )
{
result.head = result.tail = first->head;
first->head = first->head->next;
if ( first->head == NULL ) first->tail = NULL;
}
if ( !( first->head == NULL && second->head == NULL ) )
{
List tmp = merge( first, second );
result.head->next = tmp.head;
result.tail = tmp.tail;
}
return result;
}
void output( const List *list )
{
for ( const ListNode *current = list->head; current != NULL; current = current->next )
{
printf( "%d ", *current->dataPtr );
}
puts( "NULL" );
}
int main(void)
{
List even_numbers;
List odd_numbers;
makeEmpty( &even_numbers );
makeEmpty( &odd_numbers );
const int N = 10;
for ( int i = 0; i < N; i++ )
{
i % 2 == 0 ? push( &even_numbers, i )
: push( &odd_numbers, i );
}
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
List all_numbers = merge( &even_numbers, &odd_numbers );
printf( "all_numbers: " ); output( &all_numbers );
printf( "even_numbers: " ); output( &even_numbers );
printf( "odd_numbers: " ); output( &odd_numbers );
return 0;
}
The program output is
even_numbers: 0 2 4 6 8 NULL
odd_numbers: 1 3 5 7 9 NULL
all_numbers: 0 1 2 3 4 5 6 7 8 9 NULL
even_numbers: NULL
odd_numbers: NULL

Delete from double Linked List

I'm trying to delete a node from a doubly linked list but I have a problem
and this problem is when the node is the first or in the middle it prints 0 instead and it's not really deleted , but it works well when it's the last node in the list and here is the code:
dList* del(dList*ptr, int x)
{
dList *itr = NULL;
for( itr = ptr; itr != NULL; itr = itr -> next)
{
// if the element is the first in the list
if(itr -> value == x && itr -> prev == NULL)
{
itr -> next -> prev = NULL;
ptr = itr -> next;
free(itr);
}
// if the element is the last in the list
else if(itr -> value == x && itr -> next == NULL)
{
itr -> prev -> next = NULL;
free(itr);
}
// if its in the middle
else if(itr -> value == x){
(itr -> prev) -> next = itr -> next;
(itr -> next) -> prev = itr -> prev;
free(itr);
}
}
return ptr;
}
thanks in advance!
This loop
for( itr = ptr; itr != NULL; itr = itr -> next)
{
// if the element is the first in the list
if(itr -> value == x && itr -> prev == NULL)
{
itr -> next -> prev = NULL;
ptr = itr -> next;
free(itr);
}
// ...
has undefined behavior.
For example in the third expression of the for loop
itr = itr -> next
you are using already deleted pointer
free(itr);
If the list for example has only one node then itr->next is equal to NULL. So again this statement
itr -> next -> prev = NULL;
also invokes undefined behavior.
The function can look much simpler if to pass the head node by reference through pointer to it.
Also a more useful return value is the number of the deleted nodes in the list.
The function definition can look the following way
size_t del( dList **ptr, int value )
{
size_t n = 0;
while ( *ptr != NULL )
{
if ( ( *ptr )->value == value )
{
dList *tmp = *ptr;
*ptr = ( *ptr )->next;
if ( *ptr ) ( *ptr )->prev = tmp->prev;
free( tmp );
++n;
}
else
{
ptr = &( *ptr )->next;
}
}
return n;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct dList
{
int value;
struct dList *prev;
struct dList *next;
} dList;
size_t del( dList **ptr, int value )
{
size_t n = 0;
while ( *ptr != NULL )
{
if ( ( *ptr )->value == value )
{
dList *tmp = *ptr;
*ptr = ( *ptr )->next;
if ( *ptr ) ( *ptr )->prev = tmp->prev;
free( tmp );
++n;
}
else
{
ptr = &( *ptr )->next;
}
}
return n;
}
int push_front( dList **head, int value )
{
dList *new_node = malloc( sizeof( dList ) );
int success = new_node != NULL;
if ( success )
{
new_node->prev = NULL;
new_node->value = value;
new_node->next = *head;
if ( *head ) ( *head )->prev = new_node;
*head = new_node;
}
return success;
}
void out( dList *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d --> ", head->value );
}
puts( "NULL" );
}
int main(void)
{
dList *head = NULL;
push_front( &head, 1 );
push_front( &head, 2 );
push_front( &head, 1 );
out( head );
size_t n = del( &head, 1 );
printf( "%zu nodes are deleted.\n", n );
out( head );
n = del( &head, 2 );
printf( "%zu nodes are deleted.\n", n );
out( head );
return 0;
}
Its output is
1 --> 2 --> 1 --> NULL
2 nodes are deleted.
2 --> NULL
1 nodes are deleted.
NULL

Delete Node - Linked List - C

I am trying to delete a node from a linked list but I am still new to the concept of double pointers so I tried using a global variable to hold the head pointer instead. However, I get the wrong results when I try to print my list after deleting the middle node.
I saw this question
deleting a node in the middle of a linked list and I don't know how is my delete node function different from the answer.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char u8;
typedef struct Node node;
void addfirstnode( u8 );
void addnode( u8 );
void print( void );
void deletenode( u8 key );
void deleteonlynode();
void deletefirstnode();
struct Node
{
u8 x;
node *next;
};
node *head;
u8 length = 0;
void main( void )
{
u8 x;
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
while ( x != 2 )
{
switch ( x )
{
u8 n;
u8 key;
case 0: //Add node
printf( "\nPlease enter first value:" );
scanf( "%d", &n );
if ( length == 0 )
{
addfirstnode( n );
//printf("%d",head->x);
}
else
{
addnode( n );
}
printf( "\nNode added , Thank you\n" );
break;
case 1: //Print
print();
break;
case 3: //DeleteNode
printf( "\nPlease enter value to be deleted:" );
scanf( "%d", &key );
deletenode( key );
//deletefirstnode();
break;
default:
printf( "\nInvalid Choice please try again\n" );
}
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
}
//where do I use free();
}
void addfirstnode( u8 n )
{
head = ( node * ) malloc( sizeof( node ) );
head->next = NULL;
head->x = n;
length++;
}
void addnode( u8 n )
{
node *last = head;
while ( ( last->next ) != NULL )
{
last = last->next;
}
last->next = ( node * ) malloc( sizeof( node ) );
( last->next )->next = NULL;
( last->next )->x = n;
length++;
}
void print( void )
{
node *last = head;
u8 count = 1;
printf( "\n---------------------" );
if ( last == NULL )
{
printf( "\nList is empty" );
}
while ( last != NULL )
{
printf( "\nNode Number %d = %d", count, last->x );
last = last->next;
count++;
}
printf( "\n---------------------" );
printf( "\n" );
}
void deletenode( u8 key )
{
node *last = head;
//node*postlast = NULL;
if ( ( last->x == key ) && ( last->next == NULL ) )
{
deleteonlynode();
}
else
{
while ( last != NULL )
{
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next;
last->next = last->next->next;
free( temp );
length--;
}
last = last->next;
}
}
}
void deleteonlynode()
{
printf( "\n Deleting the only node" );
free( head );
head = NULL;
length--;
}
void deletefirstnode()
{
printf( "\n Deleting the first node" );
node *temp = head;
head = head->next;
free( temp );
length--;
}
The code is removing the wrong item from the linked list:
See:
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next; // last->next? No, just last.
last->next = last->next->next;
free( temp );
length--;
}
last is pointing at the element to be removed. But then the code assigns temp to point at last->next (NOT last), and then cuts that from the list.
So by looking at node->next rather than the current node, it's possible to trim it out since you're starting from the pointer before the one to remove. Basically your code was almost there already.
void deletenode( u8 key )
{
node *ptr = head;
if ( ( ptr->x == key ) )
{
// Delete the first/head element
node *temp = ptr;
head = head->next;
free( temp );
length--;
}
else
{
while ( ptr->next != NULL )
{
if ( ( ptr->next->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = ptr->next;
ptr->next = ptr->next->next;
free( temp );
length--;
}
ptr = ptr->next;
}
}
}
Also I took the liberty of renaming last to ptr because it was confusing me.
EDIT: Updated to remove the head cleanly too.
Your code seems to be deleting last->next while last should be the node that matches the key.
I guess the following code may be shorter and do the deletion
node* head;
/* returns the node* the previous_node->next should be after the deletion */
node* delete_node(node* current, u8 key) {
if (current == NULL) return NULL; // deletion comes to end
if (head->x == key) {
node* temp = current->next;
free(current);
return delete_node(temp, key);
}
current->next = delete_node(current->next, key);
return current;
}
int main() {
// build the linked list
// ...
head = delete_node(head, key);
return 0;
}
However, this implement (which uses recursion instead of loop) may cause StackOverFlow if the list is too long. I had not tested if gcc would optimize the recursion out.

Resources