/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
/*
This file contains routines for sorting numbers and determining ranks.
File: ranks.c
Author: B. Douglas Ward
Date: 31 March 2000
*/
/*---------------------------------------------------------------------------*/
/*
Structure to store list of values, sorted in increasing order.
*/
typedef struct node
{
float fval; /* floating point value */
int d; /* count of number of occurances of this value */
struct node * next; /* link to next node */
} node;
/*---------------------------------------------------------------------------*/
/*
Print contents of list, starting at smallest value.
*/
void list_print (node * n, int * count)
{
int i;
for (i = 0; i < n->d; i++)
{
printf (" %6.1f", n->fval);
*count += 1;
if (*count % 10 == 0)
printf ("\n");
}
if (n->next != NULL)
list_print (n->next, count);
}
/*---------------------------------------------------------------------------*/
/*
Delete the entire list.
*/
void list_delete (node ** n)
{
if ((*n)->next != NULL)
list_delete (&((*n)->next));
free (*n);
*n = NULL;
}
/*---------------------------------------------------------------------------*/
/*
Insert one node with value r; reset pointers.
*/
void node_insert (node ** n, float r)
{
node * ptr;
ptr = *n;
*n = (node *) malloc (sizeof(node));
(*n)->fval = r;
(*n)->d = 1;
(*n)->next = ptr;
}
/*---------------------------------------------------------------------------*/
/*
Add number r to list; if number is already in the list, just increment the
counter. Otherwise, insert new node.
*/
void node_addvalue (node ** head, float r)
{
node ** lastptr;
node * ptr;
if (*head == NULL) node_insert (head, r);
else
{
lastptr = head;
ptr = *head;
while ( (ptr->fval < r) && (ptr->next != NULL) )
{
lastptr = &(ptr->next);
ptr = ptr->next;
}
if (ptr->fval > r)
node_insert (lastptr, r);
else
if (ptr->fval == r)
ptr->d += 1;
else
node_insert (&(ptr->next), r);
}
}
/*---------------------------------------------------------------------------*/
/*
Get rank corresponding to number r. If ties exist, return average rank.
*/
float node_get_rank (node * head, float r)
{
node * ptr;
float rank;
ptr = head;
rank = 0.0;
while (ptr->fval != r)
{
rank += ptr->d;
ptr = ptr->next;
}
rank += (ptr->d + 1) / 2.0;
return (rank);
}
/*---------------------------------------------------------------------------*/
/*
Return value corresponding to the specified rank.
*/
float node_get_value (node * head, int rank)
{
node * ptr;
int k;
ptr = head;
k = 0;
while (k + ptr->d < rank)
{
k += ptr->d;
ptr = ptr->next;
}
return (ptr->fval);
}
/*---------------------------------------------------------------------------*/
/*
Return value corresponding to the median value.
*/
float node_get_median (node * head, int n)
{
float median;
if (n % 2)
median = node_get_value(head, n/2 + 1);
else
median = 0.5 * (node_get_value(head, n/2) +
node_get_value(head, n/2 + 1));
return (median);
}
/*---------------------------------------------------------------------------*/
/*
Sort the input data array of floats, and return a new array containing
the ranks of the input data.
*/
float * rank_array
(
int n, /* number of data points */
float * xarray /* array of data to be ranked */
)
{
int i; /* array index */
node * xhead = NULL; /* pointer to list of sorted values */
float * rarray = NULL; /* array of ranks */
/*----- Allocate memory for array of ranks -----*/
rarray = (float *) malloc (sizeof(float) * n); MTEST (rarray);
/*----- Enter and sort original data -----*/
for (i = 0; i < n; i++)
node_addvalue (&xhead, xarray[i]);
/*----- Get ranks of data -----*/
for (i = 0; i < n; i++)
rarray[i] = node_get_rank (xhead, xarray[i]);
/*----- Deallocate memory -----*/
list_delete (&xhead);
/*----- Return array of ranks -----*/
return (rarray);
}
/*---------------------------------------------------------------------------*/
/*
Sort the input data array of doubles, and return a new array containing
the ranks of the input data.
*/
float * rank_darray
(
int n, /* number of data points */
double * darray /* array of data to be ranked */
)
{
int i; /* array index */
node * xhead = NULL; /* pointer to list of sorted values */
float * rarray = NULL; /* array of ranks */
/*----- Allocate memory for array of ranks -----*/
rarray = (float *) malloc (sizeof(float) * n); MTEST (rarray);
/*----- Enter and sort original data -----*/
for (i = 0; i < n; i++)
node_addvalue (&xhead, (float) darray[i]);
/*----- Get ranks of data -----*/
for (i = 0; i < n; i++)
rarray[i] = node_get_rank (xhead, (float) darray[i]);
/*----- Deallocate memory -----*/
list_delete (&xhead);
/*----- Return array of ranks -----*/
return (rarray);
}
/*---------------------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1