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
Related
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
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
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.
I was just going through singly linked list.. and I copied this piece of code from reference book.. but I don't know how to run it in main.. what should I pass as an argument in struct node *new? I have no idea.. please help if possible....
struct node *insertatspecificposition( struct node *new,int n){
struct node *pred = head;
if(n<=1){
new->next = head;
return new;
}
while(--n && pred != NULL ){
pred = pred->next;
}
if(pred == NULL){
return NULL;
}
new->next = pred->next;
pred->next = new;
return head;
}
The presented function has a logical error.
When the position is set equal to 1 then the function inserts a new node before the current head node due to this code snippet
if(n<=1){
new->next = head;
return new;
}
So for example if you have an empty list (head is equal to NULL) then calling the function like
head = insertatspecificposition( a_new_node_with_value_1, 1 );
you will get the list that looks like
1 -> null
Now it is logical consistent that if for a next call of the function you will specify the position 2 you will get the list that looks like
1 -> 2 -> null
However such a call
head = insertatspecificposition( one_more_new_node_with_value_2, 2 );
returns NULL instead of returning the current value of the pointer head.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
} *head;
struct node * create( int data )
{
struct node *new = malloc( sizeof( struct node ) );
if ( new != NULL )
{
new->data = data;
new->next = NULL;
}
return new;
}
struct node *insertatspecificposition( struct node *new,int n){
struct node *pred = head;
if(n<=1){
new->next = head;
return new;
}
while(--n && pred != NULL ){
pred = pred->next;
}
if(pred == NULL){
return NULL;
}
new->next = pred->next;
pred->next = new;
return head;
}
void display( void )
{
for ( struct node *current = head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
display();
head = insertatspecificposition( create( 1 ), 1 );
display();
head = insertatspecificposition( create( 2 ), 2 );
display();
return 0;
}
The program output is
null
1 -> null
null
instead of the expected output
null
1 -> null
1 -> 2 -> null
Pay attention also to that the function should check whether the passed pointer new is not equal to NULL.
And it is not a good design when functions depend on a global variable.
As for me then I would write the function the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node * create( int data )
{
struct node *new = malloc( sizeof( struct node ) );
if ( new != NULL )
{
new->data = data;
new->next = NULL;
}
return new;
}
int insertatspecificposition( struct node **head, int data, size_t n )
{
struct node *new_node = create( data );
int success = new_node != NULL;
if ( success )
{
while ( n-- && *head != NULL )
{
head = &( *head )->next;
}
new_node->next = *head;
*head = new_node;
}
return success;
}
FILE * display( const struct node *head, FILE *fp )
{
for ( ; head != NULL; head = head->next )
{
fprintf( fp, "%d -> ", head->data );
}
fputs( "null", fp );
return fp;
}
int main(void)
{
struct node *head = NULL;
putc( '\n', display( head, stdout ) );
insertatspecificposition( &head, 1, 0 );
putc( '\n', display( head, stdout ) );
insertatspecificposition( &head, 3, 1 );
putc( '\n', display( head, stdout ) );
insertatspecificposition( &head, 2, 1 );
putc( '\n', display( head, stdout ) );
insertatspecificposition( &head, 4, 3 );
putc( '\n', display( head, stdout ) );
return 0;
}
The program output is
null
1 -> null
1 -> 3 -> null
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
If the specified position is greater than or equal to the number of nodes in the list then the new node is appended to the tail of the list.
Positions as indices for arrays in C start from 0.
Of course you need at least one more function that will clear the list that is that will free all the allocated memory.
I am not allowed to deallocate memory or allocate new memory(the list has already been allocated for me). So in essence I am trying to write a function like,
struct node* returnAndRemoveFirstNode(struct node* head)
{
struct node* returned = head;
struct node* temp = head->next;
returned->next = NULL;
head = temp;
return returned;
}
This does not work, as when I set returned->next to null I am also setting head's next to null. I am not sure how to solve this problem, I am sure there are many ways to solve it just not sure how.
For a List in the form (1->2->3->4) both the original list and the returned node look like (1->Null)
//Here is the node struct in case you need it
//I am not allowed to alter the struct..
struct node{
int data;
struct node *next;
};
I am sure you do not understand correctly the original task.
Nevertheless a function that removes the first node from the list and returns it can look the following way
struct node * returnAndRemoveFirstNode( struct node **head )
{
struct node *returned = *head;
if ( *head != NULL )
{
*head = ( *head )-next;
returned->next = NULL;
}
return returned;
}
Pay attention to that in general the list can be empty. So the pointer to the head node can be equal to NULL.
If to follow the description in your comment
The original task is to remove all nodes from the list that contain a
specific data and add all of those nodes to a different list and
return it.
then the function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
int push_front( struct node **head, int data )
{
struct node *new_node = malloc( sizeof( struct node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void output( struct node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
struct node * remove_if( struct node **head, int cmp( int data ) )
{
struct node *new_list = NULL;
for ( struct node **current = &new_list; *head != NULL; )
{
if ( cmp( ( *head )->data ) )
{
*current = *head;
*head = ( *head )->next;
( *current )->next = NULL;
current = &( *current )->next;
}
else
{
head = &( *head )->next;
}
}
return new_list;
}
int odd( int data )
{
return data % 2 != 0;
}
int even( int data )
{
return data % 2 == 0;
}
int main(void)
{
const int N = 10;
struct node *head = NULL;
for ( int i = N; i != 0; --i ) push_front( &head, i );
output( head );
putchar( '\n' );
struct node *even_head = remove_if( &head, even );
output( head );
output( even_head );
putchar( '\n' );
struct node *odd_head = remove_if( &head, odd );
output( head );
output( odd_head );
putchar( '\n' );
return 0;
}
The program output is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
1 -> 3 -> 5 -> 7 -> 9 -> null
2 -> 4 -> 6 -> 8 -> 10 -> null
null
1 -> 3 -> 5 -> 7 -> 9 -> null
struct node* returnFirstNode(struct node** head)
{
struct node* returned = *head;
struct node* next = (*head)->next;
*head = next;
returned->next = NULL;
return returned;
}