insertion in a singly linked list at a specific position - c

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.

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.

Incompatible types error from pointer to pointer

void remove_element(struct Node *list)
{
struct Node *temp = list;
printf("Enter the element value you want to remove");
int value;
scanf("%d",&value);
if(temp->data == value){ //first node is to be deleted
*list = temp->next; // error here
free(temp);
}
}
Error :incompatible types when assigning to type 'struct Node' from type 'struct Node *'|
Though this has been successfully compiled
struct Node *temp = list;
This line is similar but shows no error.
struct Node *temp = list;
is the same as
struct Node *temp;
temp = list;
So change the erroneous line to
list = temp->next;
Note that * means slightly different things depending on context. In declarations, it indicates that you want to declare a pointer instead of a regular variable. When used in an expression, it instead means that you want to dereference the pointer. There is no way to dereference it during declaration, which does not cause any problems since that would be undefined behavior anyway.
First of all the reason why you are getting error is...
*list = temp->next; //not *list it should be list
By doing so your code will compile but you will get unexpected results i think. Because:
list=temp->next // This will make the pointer to constantly point to the head
But i think you are trying to do a linear search.
Thus you also need to change the above line to
temp = temp->next;
For your code to work as you expected.
As the parameter list is declared like
struct Node *list
then the expression *list used in this statement
*list = temp->next;
has the type struct Node while the right side hand operand has the type struct Node *.
You have to write
list = temp->next;
But in any case pay attention to that the function can invoke undefined behavior when the passed list is empty. And it should search a node for the target value instead of checking only the head node whether it contains the target value.
And the worst is the function even does not change the pointer to the head node because the pointer is passed to the function by value. So this statement
list = temp->next; // error here
changes a copy of the original pointer to the head node not the original pointer itself declared in main.
The function should be defined at least like
int remove_element( struct Node **list )
{
printf( "Enter the element value you want to remove: " );
int value;
int success = scanf( "%d", &value ) == 1;
if ( success )
{
while ( *list != NULL && ( *list )->data != value )
{
list = &( *list )->next;
}
success = *list != NULL;
if ( success )
{
struct Node *tmp = *list;
*list = ( *list )->next;
free( tmp );
}
}
return success;
}
If in main you have a declaration
struct Node *list = NULL;
//...
then the function must be called like
remove_element( &list );
or something like
if ( remove_element( &list ) )
{
puts( "A node was removed." );
}
Also it would be better if the function would do only one thing: deleting a node. The prompt for a value that must be deleted should be placed outside the function. In this case the function can be defined the following way
int remove_element( struct Node **list, int value )
{
while ( *list != NULL && ( *list )->data != value )
{
list = &( *list )->next;
}
int success = *list != NULL;
if ( success )
{
struct Node *tmp = *list;
*list = ( *list )->next;
free( tmp );
}
return success;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int push_front( struct Node **list, int data )
{
struct Node *temp = malloc( sizeof( struct Node ) );
int success = temp != NULL;
if ( success )
{
temp->data = data;
temp->next = *list;
*list = temp;
}
return success;
}
void clear( struct Node **list )
{
while ( *list != NULL )
{
struct Node *temp = *list;
*list = ( *list )->next;
free( temp );
}
}
void display( const struct Node *list )
{
for ( const struct Node *current = list; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int remove_element( struct Node **list, int value )
{
while ( *list != NULL && ( *list )->data != value )
{
list = &( *list )->next;
}
int success = *list != NULL;
if ( success )
{
struct Node *tmp = *list;
*list = ( *list )->next;
free( tmp );
}
return success;
}
int main(void)
{
struct Node *list = NULL;
const int N = 10;
for ( int i = N; i != 0; i-- )
{
push_front( &list, i );
}
display( list );
int value = 1;
if ( remove_element( &list, value ) )
{
printf( "The element with the value %d was removed.\n", value );
}
display( list );
value = 10;
if ( remove_element( &list, value ) )
{
printf( "The element with the value %d was removed.\n", value );
}
display( list );
value = 5;
if ( remove_element( &list, value ) )
{
printf( "The element with the value %d was removed.\n", value );
}
display( list );
clear( &list );
display( list );
return 0;
}
Its output is
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The element with the value 1 was removed.
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
The element with the value 10 was removed.
2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
The element with the value 5 was removed.
2 -> 3 -> 4 -> 6 -> 7 -> 8 -> 9 -> null
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

Remove first node from a linked list and return it without allocating or deallocating memory.(C programming)

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;
}

Resources