And finally, this is the NEW version ... with FUNCTION POINTERS ... to handle C lists (Clist) of any struct you make ...
At the top, include stdio.h, stdlib.h, string.h ...
And then ...you will first need to typedef your struct ... List and define your clearLrec functions (as above) ... and tyepdef List* pList;
Also ... #include "Clist.h"
Also define your compare List function ...
/* your compare function prototype looks like this */
int myCompare( const pList a, const pList b );
then you can ... #include "Clist_func's.h"
/* Clist_func's.h */ /* 2016-10-07 */
/*
this version using function pointers ... has ...
msortClist, isortClist, insert_sortedClist, isSortedClist,
uniqueClist, isUniqueClist, findClist, eraseClist (i.e. erase node)
*/
#ifndef dwClist_funcs_H
#define dwClist_funcs_H
/* function protoypes ...*/
void msortClist( Clist*, int (*myCmp) (const pNode, const pNode) );
void mergesortClist( Clist*, int (*myCmp) (const pNode, const pNode) );
pNode mergeClists( Clist*, Clist*, int (*myCmp) (const pNode, const pNode) );
void update_end( Clist* );
void insert_sortedClist( Clist*, pNode, int (*myCmp) (const pNode, const pNode) );
void isortClist( Clist*, int (*myCmp) (const pNode , const pNode) );
int isSortedClist( Clist*, int (*myCmp) (const pNode, const pNode) );
void uniqueClist( Clist*, int (*myCmp) (const pNode, const pNode) );
int isUniqueClist( Clist*, int (*myCmp) (const pNode a, const pNode b) );
pNode findClist( Clist*, const pNode, int (*myCmp) (const pNode, const pNode) );
void eraseClist( Clist*, pNode );
/* function definitions ...*/
/* a recursive mergesort ... */
void mergesortClist(Clist* list, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode cur = list->start;
Clist a, b;
/* base case is a Clist of length 0 or 1 ... */
if ((cur == NULL) || (cur->next == NULL)) return;
/* split Clist into 'a' and 'b' sublists ... */
a.start = cur;
b.start = cur->next;
while((b.start != NULL) && (b.start->next != NULL))
{
cur = cur->next;
b.start = b.start->next->next;
}
b.start = cur->next;
cur->next = NULL; /* Clist divided into 2 roughly equal parts now ... */
/* recursively sort the sublists ... */
mergesortClist(&a, myCmp);
mergesortClist(&b, myCmp);
/* merge the two sorted Clists together ... */
list->start = mergeClists(&a, &b, myCmp);
}
/* merge two sorted Clists with heads 'a' and 'b' ... in sorted order */
pNode mergeClists(Clist* a, Clist* b, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode sorted, new_merged_head;
if( a->start == NULL ) return b->start;
if( b->start == NULL ) return a->start;
if( myCmp(a->start, b->start) <= 0 )
{
sorted = a->start;
a->start = a->start->next;
}
else
{
sorted = b->start;
b->start = b->start->next;
}
new_merged_head = sorted;
/* now ... */
while( a->start != NULL && b->start != NULL )
{
if( myCmp(a->start, b->start) <= 0 )
{
sorted->next = a->start;
sorted = a->start;
a->start = a->start->next;
}
else
{
sorted->next = b->start;
sorted = b->start;
b->start = b->start->next;
}
}
/* and finally ... */
if( a->start != NULL )
sorted->next = a->start;
else if( b->start != NULL )
sorted->next = b->start;
return new_merged_head;
}
void update_end( Clist* list ) /* after sort */
{
if( list->size > 1 )
{
pNode cur;
for( cur = list->start; cur->next != NULL; cur = cur->next ) ;
list->end = cur;
list->end->next = NULL;
}
}
void msortClist( Clist* clst, int (*myCmp) (const pNode r1, const pNode r2) )
{
mergesortClist( clst, myCmp );
update_end( clst );
clst->isSorted = 1;
}
int isSortedClist( Clist* c, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode p = c->start;
for( ; p != NULL && p->next != NULL; p = p->next )
if( myCmp(p->next, p) < 0 ) return 0;
return 1;
}
void uniqueClist( Clist* c, int (*myCmp) (const pNode r1, const pNode r2) )
{
int oldSize = c->size;
pNode p;
if( !isSortedClist(c, myCmp) ) msortClist( c, myCmp );
p = c->start;
while( p->next != NULL )
{
if( myCmp(p, p->next) == 0 )
{
pNode tmp = p->next;
p->next = p->next->next;
clearNode( tmp ); /* needed here for types like dynamic Cstrings, etc */
free( tmp );
-- c->size;
}
else p = p->next;
}
if( c->size < oldSize ) update_end( c ) ; /* update end ... */
}
int isUniqueClist( Clist* cl, int (*myCmp) (const pNode a, const pNode b) )
{
pNode p = cl->start;
if( cl->size < 2 ) return 1;
if( !cl->isSorted ) msortClist( cl, myCmp );
for( ; p->next != NULL; p = p->next )
{
if( myCmp( p, p->next ) == 0 ) return 0;
}
/* else */
return 1;
}
/* returns pointer if present, else returns NULL */
pNode findClist( Clist* cl, const pNode pr, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode p;
for( p = cl->start; p != NULL; p = p->next )
if( myCmp(p, pr) == 0 ) return p;
/* else if reach here ... */
return NULL;
}
void eraseClist( Clist* cl, pNode p ) /* if p valid, erase element there */
{
pNode prev = NULL, cur = cl->start;
for( ; cur != NULL && cur != p; cur = cur->next ) prev = cur;
if( cur == NULL )
{ puts( "\neraseClist ERROR! Pointer NOT found ..."); return; }
if( prev != NULL ) prev->next = cur->next; /* case of NOT FIRST element*/
else cl->start = cl->start->next; /* case of IS FIRST element*/
if( cur == cl->end ) cl->end = prev; /* case of IS LAST element*/
clearNode( cur ); /* needed here for types like dynamic C strings, etc */
free( cur ); /* free memory for dynamic Node ... */
/* now update size and return (by reference, since address passed in) */
-- cl->size;
}
/* pass in the address of the Clist and the new Node to insert ... */
void insert_sortedClist( Clist* list, pNode n, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode head;
if( !isSortedClist( list, myCmp )) msortClist( list, myCmp );
head = list->start;
/* firstly, we handle most common case where 'n' is NOT the first Node */
if( head != NULL && myCmp( n, head ) >= 0 ) /* NEED >= */
{
/* so search the linked list for the right location */
pNode cur = head;
while( cur->next != NULL && myCmp( cur->next, n ) <= 0 )
{
cur = cur->next;
}
if( cur == list->end ) list->end = n;
/* For A->B to become A->N->B */
n->next = cur->next; /* N->B */
cur->next = n; /* A->N */
}
else /* if we reach here, this IS the first node ... */
{
n->next = head; /* so set this node in first position */
list->start = n;
if( ! list->size ) list->end = n;
}
++ list->size;
}
void isortClist( Clist* list, int (*myCmp) (const pNode r1, const pNode r2) )
{
pNode cur,
nextNode;
Clist nClist;
initClist( &nClist );
for( cur = list->start; cur != NULL; cur = nextNode )
{
nextNode = cur->next; /* get copy here before next is changed below ...*/
insert_sortedClist( &nClist, cur, myCmp ); /* 'cur' already is a Node pointer */
}
/* now ... update old list with new front and back ... */
list->start = nClist.start;
list->end = nClist.end;
list->isSorted = 1;
/* size hasn't changed ... */
}
#endif