C, How to Remove Element From Queue? - c

Update: we believe to find some bugs in both solutions , you are invited to share your ideas too :)
I was trying to implement my own data structure which combines list with queue in C.
my data structure has 2 pointers, front which points to the oldest member in the queue and rear which points to the newly added member which each member points to the one which got inserted after it.
For example if I insert 1 then 2 then 3, I will have:
NULL <-3 <- 2 <- 1 // 1 is front and 3 is rear.
Now I wanted to support removing element from this DS so I starting imeplemnting it and descovvered tens of edge cases like:
if the member is the front then change the front for DS and free the member, BUT if the front is null now then change rear to null too or the other code won't work as expected.
if the member is in middle release it then go back to prev member and update its next But this seems really hard
nearly the same for the rear member except we need to update rear now and only change the pointer to the element to its right (NULL is to its left)
How am I supposed to do something like this?
I already had tens of ideas and implementation for days but simply all failed or I did something really bad making the run time complexity much higher or I wrote 170 lines which had contradictions and left unfinished conditions (by using 2 pointers).
Any help please implementing this?
struct queue_node
{
int key;
struct queue_node *next;
};
struct queue
{
int queue_size;
struct queue_node *front, *rear;
};
int requeue(struct queue *q, int val)
{
struct queue_node *tmp = q->front;
while (tmp!=NULL)
{
if (tmp->key==val)
{
if (tmp==q->front)
{
q->front=tmp->next;
if (q->front == NULL)
{
q->rear = NULL;
}
free(tmp);
}else if (tmp == q->rear)
{
}
return 0; // found
}
tmp=tmp->next;
}
return -1; // not found
}

typedef struct queue_node
{
int key;
struct queue_node *next;
}node;
typedef struct
{
size_t size;
node *head;
node *tail;
}queue;
node *append(queue *q, int key)
{
node *n = malloc(sizeof(*n));
node *c = q -> head;
if(n)
{
if(!q -> head) q -> head = n;
else
{
while(c -> next) c = c -> next;
c -> next = n;
}
n -> key = key;
n -> next = NULL;
q -> size++;
q -> tail = n;
}
return n;
}
int removenode(queue *q, int key)
{
node *n = q -> head, *p = q -> head;
int result = 0;
while(n)
{
if(n -> key == key)
{
if(n == p)
{
q -> head = n -> next;
if(!n -> next) q -> tail = n;
}
else
{
p -> next = n -> next;
if(!p -> next) q -> tail = p;
}
free(n);
q -> size--;
result = 1;
break;
}
if(p != n) p = p -> next;
n = n -> next;
}
return result;
}
void printqueue(queue *q)
{
node *n = q -> head;
printf("The queue:\n");
while(n)
{
printf("Node key = %d\n", n -> key);
n = n -> next;
}
printf("--------------\n");
if(q -> head) printf("Head key: %d, Tail key: %d, Queue size: %zu\n -------------\n\n", q -> head -> key, q -> tail -> key, q -> size);
else printf("Queue empty\n------------\n\n");
}
int main(void)
{
queue q = {0,};
append(&q,1);
append(&q,2);
append(&q,3);
append(&q,4);
printqueue(&q);
removenode(&q,3);
printqueue(&q);
removenode(&q,1);
printqueue(&q);
removenode(&q,4);
printqueue(&q);
removenode(&q,2);
printqueue(&q);
}
Result:
The queue:
Node key = 1
Node key = 2
Node key = 3
Node key = 4
--------------
Head key: 1, Tail key: 4, Queue size: 4
-------------
The queue:
Node key = 1
Node key = 2
Node key = 4
--------------
Head key: 1, Tail key: 4, Queue size: 3
-------------
The queue:
Node key = 2
Node key = 4
--------------
Head key: 2, Tail key: 4, Queue size: 2
-------------
The queue:
Node key = 2
--------------
Head key: 2, Tail key: 2, Queue size: 1
-------------
The queue:
--------------
Queue empty
------------
Program demo

The function can be defined the following way
int requeue( struct queue *q, int val )
{
struct queue_node **current = &q->front;
struct queue_node *prev = NULL;
while ( *current && ( *current )->key != val )
{
prev = *current;
current = &( *current )->next;
}
int success = *current == NULL ? -1 : 0;
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct queue_node
{
int key;
struct queue_node *next;
};
struct queue
{
int queue_size;
struct queue_node *front, *rear;
};
int requeue( struct queue *q, int val )
{
struct queue_node **current = &q->front;
struct queue_node *prev = NULL;
while ( *current && ( *current )->key != val )
{
prev = *current;
current = &( *current )->next;
}
int success = *current == NULL ? -1 : 0;
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
return success;
}
int push( struct queue *q, int key )
{
struct queue_node *node = malloc( sizeof( struct queue_node ) );
int success = node != NULL;
if ( success )
{
node->key = key;
node->next = NULL;
if ( q->rear == NULL )
{
q->front = q->rear = node;
}
else
{
q->rear = q->rear->next = node;
}
++q->queue_size;
}
return success;
}
void display( const struct queue *q )
{
for ( struct queue_node *current = q->front; current; current = current->next )
{
printf( "%d -> ", current->key );
}
puts( "null" );
}
int main(void)
{
struct queue q = { .front = NULL, .rear = NULL };
push( &q, 1 );
push( &q, 2 );
push( &q, 3 );
push( &q, 4 );
display( &q );
requeue( &q, 4 );
display( &q );
push( &q, 4 );
display( &q );
requeue( &q, 1 );
display( &q );
requeue( &q, 3 );
display( &q );
requeue( &q, 4 );
display( &q );
requeue( &q, 2 );
display( &q );
push( &q, 1 );
push( &q, 2 );
push( &q, 3 );
push( &q, 4 );
display( &q );
return 0;
}
The program output is
1 -> 2 -> 3 -> 4 -> null
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
2 -> 3 -> 4 -> null
2 -> 4 -> null
2 -> null
null
1 -> 2 -> 3 -> 4 -> null
If for testing to add a call of the function printf to this code snippet within the function requeue
if ( success == 0 )
{
struct queue_node *tmp = *current;
*current = ( *current )->next;
printf( "tmp->key == %d, tmp == %p\n", tmp->key, ( void * )tmp );
free( tmp );
--q->queue_size;
if ( *current == NULL ) q->rear = prev;
}
Then the output of the demonstrative program can look like
1 -> 2 -> 3 -> 4 -> null
tmp->key == 4, tmp == 0x55b55f9e02c0
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
tmp->key == 1, tmp == 0x55b55f9e0260
2 -> 3 -> 4 -> null
tmp->key == 3, tmp == 0x55b55f9e02a0
2 -> 4 -> null
tmp->key == 4, tmp == 0x55b55f9e02c0
2 -> null
tmp->key == 2, tmp == 0x55b55f9e0280
null
1 -> 2 -> 3 -> 4 -> null

Related

Question about about splitted Linked list

I've got this question where I'm supposed to write a function called - "createList" that gets a linked list(without a dummy element) of ints. The function should remove every element that is bigger than the previous one and the next one.
Also, I have to make a new linked list (without a dummy element) where I place all the removed elements from the original linked list. (The elements should stay in the same order that they appeared in the original linked list).
(createlist is createListEx4() in my code)
For instance, an original linked list : 3->6->1->9->8->4->5;
would be updated to : 3->1->8->4;
The "removed elements" linked list would be: 6->9->5;
The function will return a pointer to the "removed elements" linked list
I wrote this code and I cant seem to understand how to make it work.
There is a memory leak while I print the "removed elements" linked list, and doesn't return the correct elements.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef int data_type;
typedef struct Node2
{
data_type data;
struct Node2 *next;
}Node2;
Node2 * createList2(data_type data);
Node2 * addToFirst2(Node2 *head, data_type data);
Node2 * addToLast2(Node2 *head, data_type data);
void printf_List2(Node2 *head);
void Free_List2(Node2 *head);
Node2* createListEx4(Node2 *);
void Insert_To_Big(Node2 **, int);
void delete_item(Node2 **, Node2 **);
Node2* insert_list();
void main()
{
Node2 *head = NULL;
Node2 *Odd_list = NULL;
head = insert_list(); // A Function which creates a Linked List
printf("You Entered This linked-list:\n");
printf_List2(head); // A Function which prints the Imported List
Odd_list = createListEx4(head); // a Function which Returns The address to The Odd linked list
printf("The Odd Linked-List is:\n");
printf_List2(Odd_list); // A Function Which Prints the Odd List
Free_List2(Odd_list); // Free The list After we have finished using it
}
Node2* insert_list() // A function Which imports numbers to the linked list till -1
{
int Num;
Node2 *Head = NULL;
printf("Please enter the Number you want to Sort untill -1:\n");
scanf("%d", &Num);
while (Num != -1)
{
Head = addToLast2(Head, Num); // The last entered Number will be the Head
scanf("%d", &Num);
}
return Head;
}
Node2* createListEx4(Node2 *head) // **head will be in the end the Even Linked List**
{
Node2 *Big = NULL;
Node2 *temp, *step, *prev = NULL;
if (head == NULL) // if the linked list is empty
return NULL;
if (head->data > head->next->data)
{
Insert_To_Big(&Big, head->data);
temp = head;
head = head->next;
free(temp);
}
prev = head;
// At this point we start runnig the list from an even Number //
step = head;
while (step ->next ->next != NULL)
{
if ((step->data < step->next->data) && (step->next->data > step->next->next->data))
{
Insert_To_Big(&Big, step->next->data);
delete_item(&step, &prev);
}
else
{
prev = step;
step = step->next;
}
}
if (step->data < step->next->data)
{
Insert_To_Big(&Big, step->next->data);
free(step->next);
}
step = NULL;
printf("The Even Linked-List is:\n");
printf_List2(head);
Free_List2(head);
return Big;
}
void delete_item(Node2 **step, Node2 **prev) //A Funtions Which Deletes a Node and Connects the prev Node to the Next one
{
Node2 *temp = *step;
*step = (*step)->next;
(*prev)->next = *step;
free(temp);
}
void Insert_To_Big(Node2 **head, int Num) // A Function Which Creates The Odd linked list
{
*head = addToLast2(*head, Num);
}
Node2 * createList2(data_type data)
{
Node2 *temp = (Node2*)malloc(sizeof(Node2));
temp->data = data;
temp->next = NULL;
return temp;
}
Node2 * addToFirst2(Node2 *head, data_type data)
{
Node2 *temp = createList2(data);
temp->next = head;
return temp;
}
Node2 * addToLast2(Node2 *head, data_type data)
{
Node2 *p = head;
Node2 *temp = createList2(data);
if (head == NULL)
return temp;
while (p->next != NULL)
p = p->next;
p->next = temp;
return head;
}
void printf_List2(Node2 *head)
{
Node2 *p = head;
while (p != NULL)
{
printf("%d, ", p->data);
p = p->next;
}
printf("\n\n");
}
void Free_List2(Node2 *head)
{
Node2 *temp = head;
while (temp != NULL)
{
head = head->next;
free(temp);
temp = head;
}
}
My five cents.:)
Here is a demonstrative program. I named the corresponding function split. The function is called for different corner cases.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
void clear( Node **head )
{
while ( *head )
{
Node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
}
size_t assign( Node **head, const int a[], size_t n )
{
clear( head );
size_t count;
for ( size_t i = 0; i < n && ( *head = malloc( sizeof( Node ) ) ) != NULL; i++ )
{
( *head )->data = a[i];
( *head )->next = NULL;
head = &( *head )->next;
++count;
}
return count;
}
FILE * display( const Node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
Node * split( Node **head )
{
Node *out_head = NULL;
Node **out_current = &out_head;
for ( Node *prev = NULL; *head != NULL; )
{
if ( prev != NULL || ( *head )->next != NULL )
{
if ( ( prev == NULL || prev->data < ( *head )->data ) &&
( ( *head )->next == NULL || ( *head )->next->data < ( *head )->data ) )
{
Node *tmp = *head;
*head = ( *head )->next;
tmp->next = NULL;
*out_current = tmp;
out_current = &tmp->next;
}
else
{
prev = *head;
}
}
else
{
prev = *head;
}
if ( *head != NULL ) head = &( *head )->next;
}
return out_head;
}
int main(void)
{
Node *head = NULL;
int a1[] = { 3 };
assign( &head, a1, sizeof( a1 ) / sizeof( *a1 ) );
fputc( '\n', display( head, stdout ) );
Node *head2 = split( &head );
fputc( '\n', display( head, stdout ) );
fputc( '\n', display( head2, stdout ) );
clear( &head2 );
clear( &head );
putchar( '\n' );
int a2[] = { 3, 6 };
assign( &head, a2, sizeof( a2 ) / sizeof( *a2 ) );
fputc( '\n', display( head, stdout ) );
head2 = split( &head );
fputc( '\n', display( head, stdout ) );
fputc( '\n', display( head2, stdout ) );
clear( &head2 );
clear( &head );
putchar( '\n' );
int a3[] = { 6, 3 };
assign( &head, a3, sizeof( a3 ) / sizeof( *a3 ) );
fputc( '\n', display( head, stdout ) );
head2 = split( &head );
fputc( '\n', display( head, stdout ) );
fputc( '\n', display( head2, stdout ) );
clear( &head2 );
clear( &head );
putchar( '\n' );
int a4[] = { 3, 6, 1, 9, 8, 4, 5 };
assign( &head, a4, sizeof( a4 ) / sizeof( *a4 ) );
fputc( '\n', display( head, stdout ) );
head2 = split( &head );
fputc( '\n', display( head, stdout ) );
fputc( '\n', display( head2, stdout ) );
clear( &head2 );
clear( &head );
return 0;
}
The program output is
3 -> null
3 -> null
null
3 -> 6 -> null
3 -> null
6 -> null
6 -> 3 -> null
3 -> null
6 -> null
3 -> 6 -> 1 -> 9 -> 8 -> 4 -> 5 -> null
3 -> 1 -> 8 -> 4 -> null
6 -> 9 -> 5 -> null
Your code is much more complicated than need and also contains a number of logical errors.
For instance, you shouldn't use malloc and free when moving node from one list to the other. Just change pointers.
And this part from the start of createListEx4
if (head->data > head->next->data)
{
Insert_To_Big(&Big, head->data);
temp = head;
head = head->next;
free(temp);
}
You only compare head to head->next but that's not what your requirements are saying. Further, you simply free the element but it should have been moved - not freed.
Below is an implementation you can look at. There are room for improvements but I tried to keep the code simple so that it's easy to understand.
typedef int data_type;
typedef struct node
{
data_type data;
struct node *next;
} node;
node* create_static_list(void)
{
// Bypassing check for NULL for readability - don't do it in real code
node* r = NULL;
int a[] = {5, 4, 8, 9, 1, 6, 3};
for (size_t i = 0; i < sizeof a / sizeof a[0]; ++i)
{
node* t = malloc(sizeof *t);
t->next = r;
t->data = a[i];
r = t;
}
return r;
}
void add_to_other_list(node** head, node* p)
{
static node* tail = NULL;
p->next = NULL;
if (tail == NULL)
{
*head = p;
}
else
{
tail->next = p;
}
tail = p;
}
node* remove_special(node* p)
{
node* res = NULL;
if (p == NULL) return res; // 0 elements
if (p->next == NULL) return res; // 1 element
if (p->next->next == NULL) // 2 elements
{
// Special handling of last element in list
if (p->next->data > p->data)
{
// Move p->next to other list
add_to_other_list(&res, p->next);
p->next = NULL;
return res;
}
}
// Repeat as long as the list has minimum 3 elements
while (p->next->next)
{
if ((p->next->data > p->data) &&
(p->next->data > p->next->next->data))
{
// Move p-next
node* t = p->next;
p->next = p->next->next;
add_to_other_list(&res, t);
}
p = p->next;
}
if (p->next == NULL) return res; // 1 element left, just return
if (p->next->next == NULL) // 2 elements left - check last element
{
// Special handling of last element in list
if (p->next->data > p->data)
{
// Move p->next to other list
add_to_other_list(&res, p->next);
p->next = NULL;
}
}
return res;
}
// This is OPs function (expect for variable names)
void print_list(node *p)
{
while (p != NULL)
{
printf("%d, ", p->data);
p = p->next;
}
printf("\n\n");
}
int main(void)
{
node* head = create_static_list();
print_list(head);
node* removed = remove_special(head);
print_list(head);
print_list(removed);
}
OUTPUT
3, 6, 1, 9, 8, 4, 5,
3, 1, 8, 4,
6, 9, 5,
There is no need to create new elements for the returned list. Elements removed from the original list can be moved to the returned list by manipulating the links.
An element is to be moved from the original list to the returned list if its data is bigger than all of its neighboring elements that exist. There are two special cases to consider: (1) if the original list is empty, the returned list is empty; (2) if the original list consists of a single element, move it to the returned list. (Case (2) was not explicitly stated by OP, but it seems consistent. It only affects the tests for whether an element should be moved or not, which can be changed easily.)
Since the first element can be removed from the original list the function's parameter should be a double pointer, pointing to the link to the first element of the list.
The following function implements the list processing described above:
Node2 *createListEx4(Node2 **list)
{
Node2 *bigHead = NULL; /* Head of 'big' list. */
Node2 **bigEnd = &bigHead; /* Pointer to terminating link of 'big' list. */
Node2 *prev = NULL; /* Previous element to compare data with. */
Node2 *next; /* Next element to compare data with. */
Node2 *cur; /* Current element. */
while ((cur = *list) != NULL)
{
next = cur->next;
if ((!prev || cur->data > prev->data) &&
(!next || cur->data > next->data))
{
/* Move current element to 'big' list. */
*bigEnd = cur;
bigEnd = &cur->next;
*list = next;
}
else
{
/* Skip over current element. */
list = &cur->next;
}
prev = cur;
}
/* Terminate the 'big' list. */
*bigEnd = NULL;
return bigHead;
}
Examples:
Original: (null)
Returned: (null)
Remaining: (null)
Original: 1
Returned: 1
Remaining: (null)
Original: 1 2
Returned: 2
Remaining: 1
Original: 2 1
Returned: 2
Remaining: 1
Original: 1 2 3
Returned: 3
Remaining: 1 2
Original: 1 3 2
Returned: 3
Remaining: 1 2
Original: 2 1 3
Returned: 2 3
Remaining: 1
Original: 2 3 1
Returned: 3
Remaining: 2 1
Original: 3 1 2
Returned: 3 2
Remaining: 1
Original: 3 2 1
Returned: 3
Remaining: 2 1

How can I de-concatenate a Linked List into 3 separate Link Lists in C?

so I'm pretty new to Data Structures and I'm just getting introduced to Singly Linked List. The task I have right now, is to:
Concatenate 3x Linked Lists into a single Linked List
De-Concatenate the large Linked List back to 3x Linked Lists.
I have managed to do the first step, I create 3 separate Linked Lists and then append them with eachother. But I'm running into a small problem at the De-Concatenation stage and I'm hoping someone can explain what I'm doing wrong. First and foremost, here's my code...
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node * next;
} node;
node * createLL(int);
void displayLL(node * head);
node * concatenate(node * head1, node * head2, node * head3);
void deconcatenate(node * head1, node * head2, node * head3);
int main() {
struct node * head1 = NULL;
struct node * head2 = NULL;
struct node * head3 = NULL;
printf("Creating #1 Link List.. \n");
head1 = createLL(5);
displayLL(head1);
printf("\nCreating #2 Link List .. \n");
head2 = createLL(5);
displayLL(head2);
printf("\nCreating #3 Link List .. \n");
head3 = createLL(5);
displayLL(head3);
printf("\nConcatenating the Three Link Lists");
head1 = concatenate(head1,head2,head3);
displayLL(head1);
printf("\nDe-Concatenating the Link List into 3 Link Lists");
deconcatenate(head1,head2,head3);
printf("\nList #1\n");
displayLL(head1);
printf("\nList #2\n");
displayLL(head2);
printf("\nList #3\n");
displayLL(head3);
}
void deconcatenate(node * head1, node * head2, node * head3) {
struct node * temp1;
struct node * temp2;
struct node * temp3;
int i,j,k;
i = j = k = 0;
temp1 = head1;
while (i < 5) {
temp1 = temp1->next;
i++;
}
head2 = temp1; // 6
temp1 = NULL;
temp2 = head2;
while (j < 5) {
temp2 = temp2->next;
j++;
}
head3 = temp2;
temp2 = NULL;
temp3 = head3;
while (k < 5) {
temp3 = temp3->next;
k++;
}
temp3 = NULL;
}
void displayLL(node * HEAD) {
for(node * p = HEAD; p != NULL; p = p->next) {
printf("%d->",p->data);
}
printf("\n");
}
node * concatenate(node * head1, node * head2, node * head3) {
struct node * temp = head1;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = head2;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = head3;
return head1;
}
node * createLL(int n) {
int i = 0;
struct node * head = NULL;
struct node * temp = NULL;
struct node * p = NULL;
for(i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
printf("Enter data in Node #%d",i);
scanf("%d",&(temp->data));
temp->next = NULL;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
}
return head;
}
And here's the output
As you can see, after De-Concatenation, LinkList #1 only has "1" node while it should have nodes of value 1 to 5. LinkList #2 has way too many nodes than it should have. It should have nodes of value 6 to 10 but it has nodes from 6 to 15. Link List #3 is the only one with accurate value of nodes.
So what am I doing wrong in the deconcatenate Function?
The while loops inside your void deconcatenate(), shouldn't their conditions be less than other than equal to? And beside you don't need to loop through the last list just to set the last element's next pointer to NULL because you already did that when you created the very first linked list.
In my opinion the assignment is too difficult for a beginner.
If you are going to build a list from other three lists by concatenating their nodes then pointers to head nodes of the three lists shall be passed by reference because the lists will being changed within the function concatenate.
That is after calling the function the three lists shall be empty.
In C passing an object by reference to a function means passing the object indirectly through a pointer to it. In this case the function will have a direct access to the object by dereferencing the pointer that points to the object.
So the function should be declared at least like
node * concatenate(node ** head1, node ** head2, node ** head3);
The same considerations are aplayed to the function deconcatenate. After calling the function the original list shall be empty because its elements are being moved to three other lists.
That is the function should be declared at least like
void deconcatenate(node **source_head, node ** head1, node ** head2, node ** head3);
However these functions have too many parameters. As the both functions deal with a triple of pointers to head nodes it will be better to declare a structure that has three data members that keep pointers to pointers to head nodes and to use an object of this structure as a functions' parameter.
For example
typedef struct triple_lists
{
node **head1;
node **head2;
node **head3;
} triple_lists;
and
node * concatenate( triple_lists triple );
void deconcatenate( node **head, triple_lists triple );
As I have understood correctly the function deconcatenate shall split a source list into three other lists such a way that each list will contain adjacent elements of the source list and also the source list shall be divided into three more or less equal parts.
If so then approach can be the following. You need three pointers to nodes that will specify ends of each of the three lists. When the first pointer is advanced one time, the second pointer will be advanced two times and the third pointer will be advanced three times until the source node will not be exhausted.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct triple_lists
{
node **head1;
node **head2;
node **head3;
} triple_lists;
int append( node **head, int data )
{
node *new_node = malloc( sizeof( *new_node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
while ( *head ) head = &( *head )->next;
*head = new_node;
}
return success;
}
FILE * display( const node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
node * concatenate( triple_lists triple )
{
node *head = NULL;
node **current = &head;
*current = *triple.head1;
*triple.head1 = NULL;
while ( *current != NULL ) current = &( *current )->next;
*current = *triple.head2;
*triple.head2 = NULL;
while ( *current != NULL ) current = &( *current )->next;
*current = *triple.head3;
*triple.head3 = NULL;
return head;
}
void deconcatenate( node **head, triple_lists triple )
{
*triple.head1 = *head;
*triple.head2 = *head;
*triple.head3 = *head;
triple_lists tails = { head, head, head };
while ( *tails.head3 != NULL )
{
for ( size_t i = 0; *tails.head1 != NULL && i < 1; i++ )
{
tails.head1 = &( *tails.head1 )->next;
}
for ( size_t i = 0; *tails.head2 != NULL && i < 2; i++ )
{
tails.head2 = &( *tails.head2 )->next;
}
for ( size_t i = 0; *tails.head3 != NULL && i < 3; i++ )
{
tails.head3 = &( *tails.head3 )->next;
}
}
*head = NULL;
*triple.head2 = *tails.head1;
*tails.head1 = NULL;
*triple.head3 = *tails.head2;
*tails.head2 = NULL;
}
int main(void)
{
node *head1 = NULL;
node *head2 = NULL;
node *head3 = NULL;
int i = 0;
while ( i < 10 )
{
append( &head1, i++ );
}
while ( i < 15 )
{
append( &head2, i++ );
}
while ( i < 18 )
{
append( &head3, i++ );
}
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
putchar( '\n' );
triple_lists triple = { &head1, &head2, &head3 };
node *head0 = concatenate( triple );
printf( "list0: " );
putc( '\n', display( head0, stdout ) );
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
putchar( '\n' );
deconcatenate( &head0, triple );
printf( "list0: " );
putc( '\n', display( head0, stdout ) );
printf( "list1: " );
putc( '\n', display( head1, stdout ) );
printf( "list2: " );
putc( '\n', display( head2, stdout ) );
printf( "list3: " );
putc( '\n', display( head3, stdout ) );
return 0;
}
The program output is
list1: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
list2: 10 -> 11 -> 12 -> 13 -> 14 -> null
list3: 15 -> 16 -> 17 -> null
list0: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> null
list1: null
list2: null
list3: null
list0: null
list1: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> null
list2: 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> null
list3: 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> null
I did not spend my time to write a function that clears a list freeing all the allocated memory. I hope you can write such a function yourself.

Given linked list pairs swap by changing links

I have a singly linked list where I get the struct Node* head, and the return value is void. I'd like to swap in pairs without copying the data.
For example, if the input is 2->4->6 then the output is 4->2->6. But if the input is 2->4->6->7 then the output is 4->2->7->6.
Here is my code but it doesn't work.
void swapPairs(struct Node *head) {
struct Node *node;
while (head && head->next) {
struct Node *nxt = head->next;
head->next = nxt->next;
nxt->next = head;
node->next = nxt;
node = head;
head = node->next;
}
}
You need to pass the pointer to the head (or current) node by reference. Otherwise the function will deal with a copy of the value of the passed pointer. Changing the copy does not influence on the original pointer.
Here is a demonstrative program that shows how a function that swaps adjacent nodes can be written.
#include <stdio.h>
#include <stdlib.h>
#include <time.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 = ( struct 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;
}
FILE * display( const struct Node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null\n", fp );
return fp;
}
void swap( struct Node **current )
{
/*
| A | -> | A | B | -> | B | C |
head
Step 1:
| B | | A | C | | B | C |
head
Step 2:
| B | | A | C | | B | A |
head
*/
// Step 1:
struct Node *tmp = *current;
*current = ( *current )->next;
tmp->next = ( *current )->next;
// Step 2:
( *current )->next = tmp;
}
void swapPairs( struct Node **head )
{
for ( ; *head && ( *head )->next; head = &( *head )->next->next)
{
swap( head );
}
}
int main()
{
struct Node *head = NULL;
const int N = 10;
srand( ( unsigned int )time( NULL ) );
for ( int i = 0; i < N; i++ )
{
head = insert( head, rand() %( i + 1 ), rand() % N );
}
fputc( '\n', display( head, stdout ) );
swapPairs( &head );
fputc( '\n', display( head, stdout ) );
}
The program output might look like
4 -> 7 -> 8 -> 1 -> 4 -> 8 -> 9 -> 0 -> 4 -> 6 -> null
7 -> 4 -> 1 -> 8 -> 8 -> 4 -> 0 -> 9 -> 6 -> 4 -> null

Insertion Sort on Linked List in C

I am trying to perform Insertion Sort on linked list in C using following function, it gets stuck in a infinite loop. I debugged the code and found out that it works for the first pass and gets stuck in infinite loop in the second pass.
void insertion_sort()//Insertion Sort function
{
struct Node *p = root->next;
struct Node *a = NULL, *b = NULL;
while(p != NULL)
{
a = root;
while(a != p)
{
b = a;
a = a->next;
}
if(b != NULL)
b->next = a->next;
a->next = NULL;
struct Node *q = root;
struct Node* r = NULL;
while(p->data > q->data)
{
r = q;
q = q->next;
}
p->next = q;
if(r != NULL)
r->next = p;
p = p->next;
}
}
For starters it is a bad idea when a function depends on a global variable. In case of your program it means for example that you can not have two lists in one program.
I do not see where the pointer root is changed in the function insertion_sort. So even if all other code is valid nevertheless the function is incorrect because it does not change the pointer root when the value of the pointed node is unordered.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
};
int push_front( struct Node **head, int data )
{
struct Node *node = malloc( sizeof( struct Node ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = *head;
*head = node;
}
return success;
}
void insertion_sort( struct Node **head )
{
for ( struct Node **current = head; *current != NULL; )
{
struct Node **sorted = head;
while ( *sorted != *current && !( ( *current )->data < ( *sorted )->data ) )
{
sorted = &( *sorted )->next;
}
if ( *sorted != *current )
{
struct Node *tmp = *current;
*current = ( *current )->next;
tmp->next = *sorted;
*sorted = tmp;
}
else
{
current = &( *current )->next;
}
}
}
FILE * output( struct Node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int main(void)
{
enum { N = 13 };
struct Node *head = NULL;
srand( ( unsigned int )time( NULL ) );
for ( int i = 0; i < N; i++ )
{
push_front( &head, rand() % N );
}
fputc( '\n', output( head, stdout ) );
insertion_sort( &head );
fputc( '\n', output( head, stdout ) );
return 0;
}
The program output might look like
1 -> 12 -> 0 -> 4 -> 0 -> 12 -> 3 -> 7 -> 12 -> 2 -> 5 -> 9 -> 7 -> null
0 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 7 -> 7 -> 9 -> 12 -> 12 -> 12 -> null

Deleting element from linked list in C

I am trying to write a function, which is deleting a specific element from my linked list, but it crash with segmentation fault when I reach the element.
Here is a part of my code
typedef struct dlist_t {
int data;
struct dlist_t *prev, *next;
} dlist_t;
typedef struct list_t {
dlist_t *head, *tail;
} list_t;
int delElement(list_t *list, int elem) {
while (list) {
if ((list->head)->data == elem) {
list->head->next = list->head->prev;
list->head->prev = list->head->next;
free(list);
return 1;
}
list = list->head->next;
}
return 0;
}
Your function definition does not make sense. For example in this assignment statement
list = list->head->next;
there are used objects of different types in the left hand side of the assignment (the type is list_t) and in the right hand side of the assignment (the type is dlist_t).
Or this call
free(list);
tries to free the list instead of only its one node. And so on.
The function can look the following way as it is shown in thje demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct dlist_t
{
int data;
struct dlist_t *prev, *next;
} dlist_t;
typedef struct list_t
{
dlist_t *head, *tail;
} list_t;
int delElement( list_t* list, int elem )
{
dlist_t **current = &list->head;
while ( *current != NULL && ( *current )->data != elem )
{
current = &( *current )->next;
}
int success = *current != NULL;
if ( success )
{
dlist_t *tmp = *current;
if ( ( *current )->next != NULL )
{
( *current )->next->prev = ( *current )->prev;
}
else
{
list->tail = ( *current )->prev;
}
*current = ( *current )->next;
free( tmp );
}
return success;
}
int pushFront( list_t *list, int elem )
{
dlist_t *new_node = malloc( sizeof( dlist_t ) );
int success = new_node != NULL;
if ( success )
{
new_node->next = list->head;
new_node->prev = NULL;
new_node->data = elem;
if ( list->head != NULL )
{
list->head->prev = new_node;
}
else
{
list->tail = new_node;
}
list->head = new_node;
}
return success;
}
int pushBack( list_t *list, int elem )
{
dlist_t *new_node = malloc( sizeof( dlist_t ) );
int success = new_node != NULL;
if ( success )
{
new_node->prev = list->tail;
new_node->next = NULL;
new_node->data = elem;
if ( list->tail != NULL )
{
list->tail->next = new_node;
}
else
{
list->head = new_node;
}
list->tail = new_node;
}
return success;
}
void printList( list_t *list )
{
for ( dlist_t *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
void printReverseList( list_t *list )
{
for ( dlist_t *current = list->tail; current != NULL; current = current->prev )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
list_t list = { .head = NULL, .tail = NULL };
const int N = 10;
for ( int i = 0; i < N; i++ )
{
if ( i % 2 == 0 ) pushFront( &list, N / 2 - i / 2 - 1 );
else pushBack( &list, N / 2 + i / 2 );
}
printList( &list );
printReverseList( &list );
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
if ( i % 2 == 0 ) delElement( &list, i / 2 );
else delElement( &list, N - i / 2 - 1 );
printList( &list );
printReverseList( &list );
putchar( '\n' );
}
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
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> null
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> 2 -> null
3 -> 4 -> 5 -> 6 -> 7 -> null
7 -> 6 -> 5 -> 4 -> 3 -> null
3 -> 4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> 3 -> null
4 -> 5 -> 6 -> null
6 -> 5 -> 4 -> null
4 -> 5 -> null
5 -> 4 -> null
5 -> null
5 -> null
null
null
Play with the program and playing investigate it.
Do not forget to write yourself the function that frees all allocated nodes in the list.
Im not too sure what causes your crash yet, but here i have a sample of code that should work.
Struct definition:
typedef int item_type;
typedef struct _list* list;
struct node {
item_type data;
struct node *next,*prev;
};
struct _list {
struct node* head;
struct node* tail;
int size;
};
Function for "element" deletion
void list_del(list l,item_type data) {
if (list->size ==0) {
abort();
}
int i=0;
struct node* head = l->head;
while(i<list->size){
if(head->data==data){
head->prev = head->next;
l->size -= 1;
free(head);
return;
}else{
head=head->next;
}
}
}
"item_type" it's a typedef, if you have lots of functions and you shouldn't care much about types. In our example is as you wanted type int
don't worry just try this code out.This is simplest of implementation and deletion a node in linked list and still if you face any issue feel free to ask .
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
}*first=NULL;
void create(int A[],int n)
{
int i;
struct Node *t,*last;
first=(struct Node *)malloc(sizeof(struct Node));
first->data=A[0];
first->next=NULL;
last=first;
for(i=1;i<n;i++)
{
t=(struct Node*)malloc(sizeof(struct Node));
t->data=A[i];
t->next=NULL;
last->next=t;
last=t;
}
}
void Display(struct Node *p)
{
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
}
void RDisplay(struct Node *p)
{
if(p!=NULL)
{
RDisplay(p->next);
printf("%d ",p->data);
}
}
int Delete(struct Node *p,int index)
{
struct Node *q=NULL;
int x=-1,i;
if(index < 1 || index > count(p))
return -1;
if(index==1)
{
q=first;
x=first->data;
first=first->next;
free(q);
return x;
}
else
{
for(i=0;i<index-1;i++)
{
q=p;
p=p->next;
}
q->next=p->next;
x=p->data;
free(p);
return x;
}
}
int main()
{
int A[]={10,20,30,40,50};
create(A,5);
printf(“%d\n",Delete(first),2);
Display(first);
return 0;
}
So first we have created the linked list using malloc function . We have created a structure with variable which will build linked list i.e "data" and also created the pointer of struct type .
Then we have created a function name "create" to create our first node .And inserted the value according to it .
Then as you can see we g=have used for loop to fasten the process of creating the link list till the value of n.
Then for displaying the linked list we have created the function name "Display"
and if p!=NULL i.e node last column which contain address we have print the values/data of that node using for loop.
Then for deletion we have used function name "Delete" :
1st step: Is we need a pointer "p" that will point on first node .
2nd step: Now move first to next node.
3rd step: Now store the value of deleted node in new variable "x".
4th step: Delete p
The remaining code is for deleting the node from the specific position by using the two pointer, one pointer for previous node and next pointer for current node.
Just try this out or cross check with your code where you are going wrong .

Resources