ellSort
This commit is contained in:
committed by
Ralph Lange
parent
56d5a59356
commit
40d110fd7d
@@ -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);
|
||||
|
||||
|
||||
80
src/libCom/ellLib/ellSort.c
Normal file
80
src/libCom/ellLib/ellSort.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user