This commit is contained in:
Michael Davidsaver
2016-04-26 13:56:57 -04:00
committed by Ralph Lange
parent 56d5a59356
commit 40d110fd7d
2 changed files with 82 additions and 0 deletions

View File

@@ -56,6 +56,8 @@ epicsShareFunc void ellInsert (ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode);
epicsShareFunc ELLNODE * ellNth (ELLLIST *pList, int nodeNum);
epicsShareFunc ELLNODE * ellNStep (ELLNODE *pNode, int nStep);
epicsShareFunc int ellFind (ELLLIST *pList, ELLNODE *pNode);
typedef int (*pListCmp)(ELLNODE* A, ELLNODE* B);
epicsShareFunc void ellSortStable(ELLLIST *pList, pListCmp);
epicsShareFunc void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc);
epicsShareFunc void ellVerify (ELLLIST *pList);

View File

@@ -0,0 +1,80 @@
/*
* Use of mergesort algorithm based on analysis by
* http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
*/
#include <stdlib.h>
#define epicsExportSharedSymbols
#include "epicsAssert.h"
#include "ellLib.h"
static void ellMoveN(ELLLIST* pTo, ELLLIST* pFrom, int count )
{
for(;count && ellCount(pFrom); count--) {
ELLNODE *node = ellGet(pFrom);
ellAdd(pTo, node);
}
}
/* Stable (MergeSort) to given list.
* The comparison function cmp(A,B) is expected
* to return -1 for A<B, 0 for A==B, and 1 for A>B.
*/
void ellSortStable(ELLLIST *pList, pListCmp cmp)
{
ELLLIST INP, P, Q;
size_t insize = 1; /* initial sub-list size */
if(ellCount(pList)<=1)
return;
ellInit(&INP);
ellInit(&P);
ellInit(&Q);
/* Process is to iteratively sort
* a sequence of sub-lists of size 'insize'
*/
while(insize < ellCount(pList)) {
assert(ellCount(&INP)==0);
/* shift previous results to inputs */
ellConcat(&INP, pList);
assert(ellCount(pList)==0);
while(ellCount(&INP))
{
ELLNODE *p, *q;
assert(ellCount(&P)==0);
assert(ellCount(&Q)==0);
/* Pull out the next pair of sub-lists */
ellMoveN(&Q, &INP, insize);
ellMoveN(&P, &INP, insize);
/* merge these sub-lists */
while((p=ellFirst(&P)) && (q=ellFirst(&Q)))
{
if((*cmp)(p,q) < 0) {
ellAdd(pList, ellGet(&P));
} else {
ellAdd(pList, ellGet(&Q));
}
}
/* concatinate any remaining to result */
if(ellFirst(&P))
ellConcat(pList, &P);
else if(ellFirst(&Q))
ellConcat(pList, &Q);
assert(!ellFirst(&P) && !ellFirst(&Q));
}
insize *= 2;
}
}