TIP: Click on subject to list as thread! ANSI
echo: c_echo
to: ALL
from: GEORGE WHITE
date: 1998-04-26 17:36:00
subject: Natural merge sort 1/

/************************ natmerge.c ***********************************/
/*       Copyright 1998 G. White              */
/* 26/04/98 Initial public release            */
/* Implementation of natural 2-way merge sort */
/* Based on Knuth, Vol 3, page 160 - 163      */
/* You may use this code freely. You may also distribute it, provided     */
/* no charge is levied beyond that for its distribution medium.           */
/* The author makes no warranty of the code's usefulness for any purpose, */
/* and accepts no responsibility for any damages caused by its misuse.    */
/* nat_merge() sorts an array, the type is controlled by the #define T    */
/* and can be any intrinsic type.                                         */
/* mat_merge_p() uses an external comparison routine and takes the same   */
/* parameter list as the standard library qsort(). It uses the standard   */
/* library memcpy() routine to move elements.                             */
/* Both versions allocate a local work area from the heap the same size   */
/* as the array to be sorted, and return 0 if unable to allocate the work */
/* area, otherwise they return 1.                                         */
#include         /* for memcpy() prototype */
#include      /* for malloc() prototype */
/* Now specify the intrinsic type for nat_merge() */
#define T       short
/* Prototypes */
int nat_merge (T *array,int n);
int nat_merge_p (void *base,
    size_t num,
    size_t width,
    int (*compare)(const void *, const void *) );
/* Var  Values Description                      */
/* s =  0/1 array transfer direction, 0 for array to t_array */
/* d = -1/1 dest move direction                 */
/* f =  1/0 completion flag, 1 if done          */
/* i = current left position in source array    */
/* j = current right position in source array   */
/* k = destination position                     */
/* l = save for alternate destination position  */
/* temp = used when exchanging k & l            */
/* t_array = temporary array, the same size as array to sort */
/* Return Values                                       */
/* Returns 0 if unable to malloc() the temporary array */
/* Returns 1 otherwise                                 */
/******************************************************************/
int nat_merge_p (void *array,size_t n,size_t width,
                int (*compare)(const void *, const void *))
{
char    *i,*j,*k,*l,*temp,*t_array;
int     s,d,f;
if (NULL == (t_array = (char *) calloc (n,width)))
    return 0;           /* Not enough heap available, fail cleanly */
s = 0;                  /* Sort from array to t_array */
do
    {
    if (s == 0)
        {                       /* Transfer from array to t_array */
        i = (char *)array;
        j = (char *)array + (n - 1) * width;
        k = t_array;
        l = t_array + (n - 1) * width;
        }
    else
        {                       /* transfer t_array to array */
        k = (char *)array;
        l = (char *)array + (n - 1) * width;
        i = t_array;
        j = t_array + (n - 1) * width;
        }
    d = f = 1;                  /* set increasing k and done flag */
    while (i != j)
        {
        if ((*compare)(i,j) <= 0)
            {                           /* Start from left of source array */
            memcpy (k,i,width);         /* and transfer to destination      
/
            k += d * width;             /* move k in the required direction 
/
            i += width;                 /* and incremet i to the next */
            if ((*compare)(i - width,i) > 0)
                {       /* until the next element is out of sequence */
                do
                    {
                    memcpy (k,j,width); /* then transfer from the other end 
/
                    k += d * width;
                    j -= width;
                    }           /* until out of sequence */
                while ((*compare)((j + width),j) <= 0);
                f = 0;          /* clear completion flag, now store data */
                d = -d;         /* in reversed order to the last one     */
                temp = k;       /* to the current position from the      */
                k = l;          /* other end of the array                */
                l = temp;
                }
            }
        else
            {                   /* start from right of source */
            memcpy (k,j,width); /* and otherwise as above */
            k += d * width;
            j -= width;
            if ((*compare)((j + width),j) > 0)
                {
                do
                    {
                    memcpy (k,i,width);
                    k += d * width;
                    i += width;
                    }
                while ((*compare)((i - width),i) <= 0);
                f = 0;
                d = -d;
                temp = k;
                k = l;
                l = temp;
                }
            }
        }
    memcpy (k,i,width);         /* transfer the last element */
    s = 1 - s;                  /* and swap array usage      */
    }
while (0 == f);
if (s)                          /* if data in t_array, move it to array */
    for (i = array,j = t_array,s = 0;s < n * width;s++)
        *i++ = *j++;
free (t_array);                 /* tidy up */
return 1;                       /* and show all went well */
}
>>> Continued to next message
 * SLMR 2.1a * Wastebasket: Something to throw things near.
--- Maximus/2 3.01
---------------
* Origin: DoNoR/2,Woking UK (44-1483-717905) (2:440/4)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.