Partition a Linked List (C) - c

The problem asks us to split a Linked List based on a pivot value
(1->2->4->6->3->5 pivot = 5 ) => ( 1->2->4->3->5->6)
My Solution to the problem was to create 3 new linked list and split based on the pivot value. However I am not able to concatenate the 3 linked list together and let head point to the new concatenated linked list. Please guide me through on how I can concatenate the 3 linked list and let head point to the concatenated linked list.
void triPartition(ListNode** head, int pivot){
ListNode *cur;
ListNode ** Small = NULL;
ListNode ** Equal = NULL;
ListNode ** Large = NULL;
int Scount = 0 , Ecount = 0 , Lcount = 0;
cur = (*head);
if(cur == NULL)
{
return 0;
}
if(cur->next == NULL)
{
return 0;
}
while(cur != NULL)
{
if(cur->item == pivot)
{
insertNode(&Equal, Ecount, cur->item);
Ecount++;
}
else if(cur->item < pivot)
{
insertNode(&Small, Scount, cur->item);
Scount++;
}
else
{
insertNode(&Large, Lcount, cur->item);
Lcount++;
}
cur = cur->next;
}
This part of my solution does not work
*head = Small;
while((*Small)->next!=NULL)
{
Small = (*Small)->next;
}
(*Small)->next = Equal;
while((*Equal)->next!=NULL)
{
Equal = (*Equal)->next;
}
(*Equal)->next = Large;
}

It seems that no professional programmer are going tp help you. So we beginners should help each other ourselves.:)
Using your approach to the function implementation by means of creating at first three separate lists and then combining them in one list I can suggest the following function definition shown in the demonstration program below.
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode
{
int item;
struct ListNode *next;
} ListNode;
void clear( ListNode **head )
{
while (*head)
{
ListNode *current = *head;
*head = ( *head )->next;
free( current );
}
}
size_t assign( ListNode **head, const int a[], size_t n )
{
clear( head );
size_t i = 0;
for ( ; i != n && ( *head = malloc( sizeof( ListNode ) ) ) != NULL; i++)
{
( *head )->item = a[i];
( *head )->next = NULL;
head = &( *head )->next;
}
return i;
}
FILE *display( const ListNode * const head, FILE *fp )
{
for ( const ListNode *current = head; current != NULL; current = current->next)
{
fprintf( fp, "%d -> ", current->item );
}
fputs( "null", fp);
return fp;
}
void triPartition( ListNode **head, int pivot )
{
ListNode * small = NULL;
ListNode * equal = NULL;
ListNode * large = NULL;
ListNode ** small_ptr = &small;
ListNode ** equal_ptr = &equal;
ListNode ** large_ptr = &large;
for ( ListNode *current = *head; current != NULL; )
{
ListNode *tmp = current;
current = current->next;
tmp->next = NULL;
if ( tmp->item < pivot )
{
*small_ptr = tmp;
small_ptr = &( *small_ptr )->next;
}
else if ( pivot < tmp->item )
{
*large_ptr = tmp;
large_ptr = &( *large_ptr )->next;
}
else
{
*equal_ptr = tmp;
equal_ptr = &( *equal_ptr )->next;
}
}
*equal_ptr = large;
*small_ptr = equal;
*head = small;
}
int main( void )
{
int a[] = { 1, 2, 4, 6, 3, 5 };
ListNode *head = NULL;
assign( &head, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display( head, stdout ) );
triPartition( &head, 5 );
fputc( '\n', display( head, stdout ) );
clear( &head );
}
The program output is
1 -> 2 -> 4 -> 6 -> 3 -> 5 -> null
1 -> 2 -> 4 -> 3 -> 5 -> 6 -> null

Related

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

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

Having a hard time creating a function for lists in C

I am trying to create a function delz() which deletes a given number from the end of the list, I tried recursively and with a while loop and I can't figure it out.
Example: [ 3 | next ] - [ 4 | next ] - [ 3 | next ] - [ 7 | next ] -----> [ 3 | next ] - [ 4 | next ] - [ 7 | next ]
list delz (int val, list l) {
if(l == NULL)
return NULL;
else {
list head = l;
list tmp = l;
list tail;
list temp;
while(l != NULL){
if(l->value == val) {
list tail = l->next;
head->next = tail;
}
temp = head;
head = tmp;
l = l->next;
}
return head;
}
}
typedef struct node {
int value;
struct node *next;
} node, *list;
The function will be simpler if to pass to the function the pointer to the head node by reference.
Here is a demonstrative program. I used my own singly-linked list definition because you did not show your own. Also it is a bad idea to introduce a typedef for a pointer type.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int val;
struct Node *next;
};
void assign( struct Node **head, const int a[], size_t n )
{
if ( *head )
{
struct Node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
for ( size_t i = 0; i < n; i++ )
{
*head = malloc( sizeof( struct Node ) );
( *head )->val = a[i];
( *head )->next = NULL;
head = &( *head )->next;
}
}
void display( const struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->val );
}
puts( "null" );
}
int remove_last( struct Node **head, int val )
{
struct Node **target = NULL;
for ( ; *head != NULL; head = &( *head )->next )
{
if ( ( *head )->val == val ) target = head;
}
int success = target != NULL;
if ( success )
{
struct Node *tmp = *target;
*target = ( *target )->next;
free( tmp );
}
return success;
}
int main(void)
{
int a[] = { 3, 4, 3, 7 };
const size_t N = sizeof( a ) / sizeof( *a );
struct Node *head = NULL;
assign( &head, a, N );
display( head );
int val = 3;
if ( remove_last( &head, val ) )
{
printf( "The last node with the value %d is removed.\n", val );
}
display( head );
return 0;
}
The program output is
3 -> 4 -> 3 -> 7 -> null
The last node with the value 3 is removed.
3 -> 4 -> 7 -> null

How to delete multiple occurrences of multiple variables in a linked list in c

I am a beginner in c programming and i have been trying for several days to solve the following question:
how to remove numbers that appear at least 3 times in the following list:
3→3→1→2→4→3→5→3→5→4
which makes the result:
1→2→4→5→5→4.
Now i know how to delete multiple occurrences of "one" key in a linked list, for example deleting all occurrences of "1" in the linked list, but can't seem to understand how to delete multiple occurrences of multiple variables. It's just killing me. I would really appreciate it if anyone could help. thanks in advance.
It seems nobody hurries to help you.:)
It is simpler to write the function if to pass the pointer head to the function by reference.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int insert( 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 out( struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void remove_repetitive( struct Node **head )
{
const size_t LIMIT = 3;
while ( *head != NULL )
{
size_t count = 1;
int data = ( *head )->data;
for ( struct Node *node = ( *head )->next;
count < LIMIT && node != NULL; node = node->next )
{
if ( node->data == data ) ++count;
}
if ( count == LIMIT )
{
for ( struct Node **node = head; *node != NULL; )
{
if ( ( *node )->data == data )
{
struct Node *tmp = *node;
*node = ( *node )->next;
free( tmp );
}
else
{
node = &( *node )->next;
}
}
}
else
{
head = &( *head )->next;
}
}
}
int main(void)
{
struct Node *head = NULL;
int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
insert( &head, a[i] );
}
out( head );
remove_repetitive( &head );
out( head );
return 0;
}
The program output is
3 -> 3 -> 1 -> 2 -> 4 -> 3 -> 5 -> 3 -> 5 -> 4 -> null
1 -> 2 -> 4 -> 5 -> 5 -> 4 -> null
The function remove_repetitive can be splitted out into two functions as it is shown below.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int insert( 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 out( struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void remove_all( struct Node **head, int data )
{
while ( *head != NULL )
{
if ( ( *head )->data == data )
{
struct Node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
else
{
head = &( *head )->next;
}
}
}
void remove_repetitive( struct Node **head )
{
const size_t LIMIT = 3;
while ( *head != NULL )
{
size_t count = 1;
int data = ( *head )->data;
for ( struct Node *node = ( *head )->next;
count < LIMIT && node != NULL; node = node->next )
{
if ( node->data == data ) ++count;
}
if ( count == LIMIT )
{
remove_all( head, data );
}
else
{
head = &( *head )->next;
}
}
}
int main(void)
{
struct Node *head = NULL;
int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
insert( &head, a[i] );
}
out( head );
remove_repetitive( &head );
out( head );
return 0;
}
The program output is the same as shown above.

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

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

how to connect a struct nodes(linked lists)?

i want to make a new node that is a copy of Node_1 connected to Node_2
, the problem is that i need to choose elemenets in each node that
accept a specific condition thhat i insert in the connection function
. for example if i have two nodes that i want to connect to each other
(the second one at the end of the first one) , but i want to chose the
elements in each node that are for example odd ! (for example : first
linked list has the following elements(1 2 3 ) , and the second linked
list has the following elements (4 5 6) then i want to have a new linked list >that has the following elements : (1 3 5)
now my main problem is that i need to work with pointers to
functions because each time i want to give the function different
conditions .
i wrote this function with the assumption that i have a
ConditionFunction, but actually i an kinda stuck on how to make a
ConditionFunction in the main function that can actually do what i
want :/ (for example linke only the odd numbers)
i wrote this function to connect the two linked lists :
// the struct:
typedef struct node_t* Node;
struct node_t {
Element element;
Node next;
};
// ConditionNode a pointer to a function that has condition
// CopyNode a pointer to a function that copy's the node
Node concatLists(Node Node_1,Node Node_2,ConditionNode ConditionFunction,CopyNode copyFunction,void* condition){
Node currentNode=NULL;
Node* New_Node=NULL;
Node head=NULL;
while(Node_1!=NULL){
if(ConditionFunction(Node_1->element,condition)==0){
Node_Result=create_node(&New_Node);
if(head==NULL){
head=New_Node;
currentNode=New_Node;
}
currentNode->next=New_Node;
currentNode=New_Node;
Node_1=GetNextNode(Node_1);
}
else{
Node_1=GetNextNode(Node_1);
}
}
while(Node_2!=NULL){
if(CmpFunction(Node_2->element,condition)!=0){
if(head==NULL){
head=New_Node;
currentNode=New_Node;
}
currentNode->next=New_Node;
currentNode=New_Node;
Node_2=GetNextNode(Node_2);
} else {
Node_1=GetNextNode(Node_1);
}
}
return head;
}
Node_Result create_node(Node* CreatedNode) {
Node newNode = malloc(sizeof(*newNode));
if(!newNode) {
return MEM_PROBLEM;
}
newNode->element =0;
newNode->next = NULL;
*CreatedNode=newNode;
return NODE_SUCCESS;
}
Node GetNextNode(Node node){
if(node==NULL){
return NULL;
}
return node->next;
}
i wrote an example but i think it is wrong :\
int main(){
int array_1[3]={1,2,3};
int array_2[4]={4,5,6,7};
Node head_1=createAllNode(array_1,3);
Node head_2=createAllNode(array_2,4);
int num=2;
Node oddhead=concatLists(head_1,head_2,&copyInt,&checkIfOdd,&num);
printIntElements(oddhead);
return 0;
}
static Node createAllNode(int* array,int len){
Node head;
Node_Result result=create_node(&head);
if(result!=NODE_SUCCESS){
return NULL;
}
Node new_node=NULL;
int j=0;
while(len){
/*int *num=malloc(sizeof(*num));
if(num==NULL){
return NULL;
} */
int element=array[j];
head->element=*(int *)element;
if(j != len-1){
result=create_node(&new_node);
}
if(Node_Result!=NODE_SUCCESS){
return NULL;
}
head->next=new_node;
head=new_node;
new_node=GetNextNode(new_node);
j++;
len--;
}
return head;
}
static void* copyInt(void* num){
int* newInt=malloc(sizeof(*newInt));
*newInt=*(int*)num;
return newInt;
}
/*
static bool PrimaryIntNode(void*num1,void* num2){
}
*/
static void printIntElements(Node head){
while(head!=NULL){
printf("%d",(int*) head->element);
head=GetNextNode(head);
}
}
static bool checkIfOdd(Element num1,int num2){
int num=*(int *)num1;
if(num<0){
num *=-1;
}
return num % num2 != 0;
}
and i call the coonect list function like this in the main function :
Node oddhead=concatLists(head_1,head_2,&copyNode,&checkifIdd,&num);
can anyone just show me a correct example oh how actually use a
function like this in main !! because i get all kinda of errors in
eclipse ..
I will not use your definitions because they are confusing. I will just demonstrate how two lists can be concatenated by selecting nodes that satisfy some condition. You can use the presented demonstrative program as a base for your own list implementation.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
void insert( struct node **head, const int a[], size_t n )
{
if ( *head != NULL ) head = &( *head )->next;
for ( size_t i = 0; i < n; i++ )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->data = a[i];
tmp->next = *head;
*head = tmp;
head = &( *head )->next;
}
}
struct node * concatLists( struct node *head1, struct node *head2, int cmp( struct node * ) )
{
struct node *head = NULL;
struct node **current = &head;
for ( ; head1 != NULL; head1 = head1->next )
{
if ( cmp( head1 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = head1->data;
( *current )->next = NULL;
current = &( *current )->next;
}
}
for ( ; head2 != NULL; head2 = head2->next )
{
if ( cmp( head2 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = head2->data;
( *current )->next = NULL;
current = &( *current )->next;
}
}
return head;
}
void output( struct node *head )
{
for ( ; head != NULL; head= head->next )
{
printf( "%d ", head->data );
}
}
int odd( struct node *n )
{
return n->data % 2;
}
int main( void )
{
struct node *head1 = NULL;
struct node *head2 = NULL;
int a1[] = { 1, 2, 3 };
int a2[] = { 4, 5, 6 };
const size_t N1 = sizeof( a1 ) / sizeof( *a1 );
const size_t N2 = sizeof( a2 ) / sizeof( *a2 );
insert( &head1, a1, N1 );
insert( &head2, a2, N2 );
struct node *head3 = concatLists( head1, head2, odd );
output( head1 );
putchar( '\n' );
output( head2 );
putchar( '\n' );
output( head3 );
putchar( '\n' );
return 0;
}
The program output is
1 2 3
4 5 6
1 3 5

Resources