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
Related
What I'm doing is that first I reversed the linked list and then actually I'm trying to get the nth value of a node. The problem is that the function isn't doing anything after it reverses the linked list and doesn't give an error for some reason.
Here's my code:
#include<stdlib.h>
#include<assert.h>
// 1. Create a linked list first
struct Node {
int data;
struct Node* next;
};
// 2. Create traversal function for linked list
void linkedListTraversal(struct Node* ptr) {
while (ptr != NULL) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
// 3. Write a function to get the node value from the tail of the linked list
int getNode(struct Node* head, int positionFromTail) {
int value;
struct Node* prevNode = NULL;
struct Node* currNode = head;
struct Node* nextNode;
while (currNode != NULL) {
nextNode = currNode->next;
currNode->next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
head = prevNode;
struct Node* ptr = head;
int count = 0;
while (ptr != NULL) {
if (count == positionFromTail) {
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
assert(0);
}
int main() {
struct Node* head;
struct Node* second;
struct Node* third;
struct Node* fourth;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
fourth = (struct Node*)malloc(sizeof(struct Node));
head->data = 3;
head->next = second;
second->data = 2;
second->next = third;
third->data = 1;
third->next = fourth;
fourth->data = 0;
fourth->next = NULL;
linkedListTraversal(head);
printf("The value of the node is %d", getNode(head, 2));
}
Here's my output and any help will be appreciated.
3
2
1
0
You can have an infinite loop because the pointer ptr is changed only when the condition of the if statement within the loop evaluates to true
while (ptr!=NULL)
{
if (count == positionFromTail)
{
return (ptr->data);
count = count + 1;
ptr = ptr->next;
}
}
Rewrite the for loop at least for example like
while ( ptr != NULL && positionFromTail-- )
{
ptr = ptr->next;
}
if ( ptr != NULL )
{
return ptr->data;
}
else
{
// return some value
return -1;
}
Also the parameter positionFromTail shall have an unsigned integer type. Otherwise you need to check in the beginning of the function whether it has a negative value.
Pay attention to that after exiting the function your list will be broken. The pointer head in main will not be changed after calling the function but the value of the data member next of the node pointed to by the pointer and of other nodes will be changed. So in general your approach is incorrect.
There is no need to reverse the list to find an element at the given position counted from the end of the list.
For starters I would declare the function the following way
int getNode( const struct Node *head, int pos, int *data );
That is the function returns either 1 if there exists a node with the specified position or 0 otherwise. If there is a node with the specified position then the stored value is written in the dereferenced parameter data.
If the value of the parameter pos is not negative then counting of nodes starts from the head otherwise from the end of the list.
Here is a demonstration program.
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
void clear( struct Node **head )
{
while (*head)
{
struct Node *current = *head;
*head = ( *head )->next;
free( current );
}
}
size_t create( struct Node **head, const int a[], size_t n )
{
clear( head );
size_t i = 0;
while (n-- && ( *head = malloc( sizeof( struct Node ) ) ) != NULL )
{
( *head )->data = *a++;
( *head )->next = NULL;
++i;
head = &( *head )->next;
}
return i;
}
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 getNode( const struct Node *head, int pos, int *data )
{
int success = 0;
if (!( pos < 0 ))
{
while (head != NULL && pos--)
{
head = head->next;
}
if (( success = head != NULL )) *data = head->data;
}
else
{
const struct Node *current = head;
for ( ;current != NULL && pos; ++pos )
{
current = current->next;
}
while (current != NULL )
{
head = head->next;
current = current->next;
}
if (( success = pos == 0 )) *data = head->data;
}
return success;
}
int main( void )
{
struct Node *head = NULL;
const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( &head, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display(head, stdout ) );
for (int i = 0, data; getNode( head, i, &data ); i++)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
for (int i = -1, data; getNode( head, i, &data ); i--)
{
printf( "%d: %d; ", i, data );
}
putchar( '\n' );
clear( &head );
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
0: 0; 1: 1; 2: 2; 3: 3; 4: 4; 5: 5; 6: 6; 7: 7; 8: 8; 9: 9;
-1: 9; -2: 8; -3: 7; -4: 6; -5: 5; -6: 4; -7: 3; -8: 2; -9: 1; -10: 0;
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 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
I have this piece of code, it deletes the last element from a linked list. What changes do I have to make so it will delete the last TWO elements of the linked list?
void deletesEnd() {
struct node *temp, *last;
temp = head;
last = temp;
while (temp != NULL && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == temp) {
free(temp);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
}
The simplest solution to remove the last 2 elements of the list is to call deletesEnd() twice. Note that deletesEnd() should take head as an argument and return the new value. You would delete the last 2 by issuing a nested call:
struct node *deletesEnd(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
free(head);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
return head;
}
Delete the last element: head = deletesEnd(head);
Delete the last 2 elements: head = deletesEnd(deletesEnd(head));
The simplicity of the design more than compensates for the overhead of enumerating the list twice.
If you absolutely want a specific function, you can extend your approach this way:
struct node *deleteLast2Nodes(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL && temp->next->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
if (head) {
free(head->next);
}
free(head);
head = NULL;
} else {
free(last->next->next);
free(last->next);
last->next = NULL;
}
return head;
}
Here is a demonstrative program that shows how two last nodes can be deleted simultaneously. In fact the function is similar to your function except it checks not only the next node but also the next->next node.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
struct node *next;
} *head;
void push( int value )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->value = value;
tmp->next = head;
head = tmp;
}
void display()
{
for ( struct node *current = head; current; current = current->next )
{
printf( "%d ", current->value );
}
}
void deleteLastTwo()
{
struct node *current = head;
struct node *prev = head;
if ( current && current->next )
{
while ( current->next->next )
{
prev = current;
current = current->next;
}
}
if ( current )
{
if ( current->next )
{
free( current->next );
}
if ( prev == current )
{
head = NULL;
}
else
{
prev->next = NULL;
}
free( current );
}
}
int main(void)
{
const int N = 11;
for ( int i = N; i != 0; i-- ) push( i - 1 );
display();
printf( "\n" );
while ( head )
{
deleteLastTwo();
display();
printf( "\n" );
}
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6
0 1 2 3 4
0 1 2
0
Take into account that it is not a good idea when the head node is declared like a global variable. It is better when it can be declared like a local variable. In this case you will need to rewrite the methods of the list because in most cases the current methods will not work correctly.
This logic will delete your last 2 node in singly linked list.
void deletesEnd()
{
struct node *temp, *last;
temp = head;
last = temp;
while (temp->next->next != NULL)
{
last = temp->next;
if(last->next->next!=NULL)
temp = temp->next;
else
break;
}
struct node *ptr=last->next;
last->next=ptr->next;
free(ptr);
temp->next=last->next;
free(last);
}
For fun & education: simple recursive version.
The function return := the number of nodes below us
After the recursion returns, we can decide if we are too close to the tail.
and remove ourselves
because we pass a pointer to pointer, this should also work for lists of size=2 and smaller
unsigned del_tail_n(struct llist **pp, unsigned nn)
{
unsigned pos;
if (!*pp) return 0;
// this recursive call returns 0 iff (*pp)->next is NULL
pos = del_tail_n( &(*pp)->next, nn);
if (pos < nn) {
// free (*pp);
*pp = NULL;
}
return 1+pos;
}
For those who don't like recursion, here is a non-recursive version.
[do note that both versions work for empty lists (*pp == NULL) , or for lists smaller than nn ]
void del_tail_n2(struct llist **pp, unsigned nn)
{
struct llist *p;
/* Advance p pointer n positions down, starting from *pp. */
for (p= *pp; p; p=p->next) {
if (nn-- < 1) break;
}
/* Do a synchronous walk down for both p and *pp, until p is NULL. */
for ( ; p; p=p->next) {
pp = &(*pp)->next;
}
/* Now, *pp is the first node to delete
** Delete it and everything below it.
*/
for ( ;(p = *pp); ){
*pp = p->next;
// free (p);
}
return;
}