The R Project SVN R-packages

Rev

Rev 6391 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/*
 * quick sort routine : sort a vector of floats, and carry along an int
 *
 *  x:     vector to sort on
 *  start: first element of x to sort
 *  stop:  last element of x to sort
 *  cvec:  a vector to carry along
 */
#include "rpart.h"
#include "rpartproto.h"

void
mysort(int start, int stop, double *x, int *cvec)
{
    int i, j, k;
    double temp, median;
    int tempd;

    while (start < stop) {
       /*
    * first-- if the list is short, do an ordinary insertion sort
    */
    if ((stop - start) < 11) {
        for (i = start + 1; i <= stop; i++) {
        temp = x[i];
        tempd = cvec[i];
        j = i - 1;

        while (j >= start && x[j] > temp) {
            x[j + 1] = x[j];
            cvec[j + 1] = cvec[j];
            j--;
        }
        x[j + 1] = temp;
        cvec[j + 1] = tempd;
        }
        return;
    }
    /*
     * list is longer -- split it into two
     *  I use the median of 3 values as the split point
     */
    i = start;
    j = stop;
    k = (start + stop) / 2;

    median = x[k];
    if (x[i] >= x[k]) {     /* one of j or k is smallest */
        if (x[j] > x[k]) {  /* k is smallest */
        if (x[i] > x[j])
            median = x[j];
        else
            median = x[i];
        }
    } else {
        if (x[j] < x[k]) {
        if (x[i] > x[j])
            median = x[i];
        else
            median = x[j];
        }
    }

    /*
     *  Now actually do the partitioning
     *   Because we must have at least one element >= median, "i"
     *   will never run over the end of the array.  Similar logic
     *   applies to j.
     * A note on the use of "<" rather than "<=".  If a list has lots
     *   of identical elements, e.g. 80/100 are "3.5", then we will
     *   often go to the swap step with x[i]=x[j]=median.  But we will
     *   get the pointers i and j to meet approximately in the middle of
     *   the list, and that is THE important condition for speed in a
     *   quicksort.
     *
     */
    while (i < j) {
       /*
        * top pointer down till it points at something too large
        */
        while (x[i] < median)
        i++;

       /*
        * bottom pointer up until it points at something too small
        */
        while (x[j] > median)
        j--;

        if (i < j) {
        if (x[i] > x[j]) {      /* swap */
            temp = x[i];
            x[i] = x[j];
            x[j] = temp;
            tempd = cvec[i];
            cvec[i] = cvec[j];
            cvec[j] = tempd;
        }
        i++;
        j--;
        }
    }

    /*
     * The while() step helps if there are lots of ties.  It will break
     *  the list into 3 parts: < median, ==median, >=median, of which only
     *  the top and bottom ones need further attention.
     * The ">=" is needed because i may be  == to j
     */
    while (x[i] >= median && i > start)
        i--;
    while (x[j] <= median && j < stop)
        j++;

    /*
     * list has been split, now do a recursive call
     *   always recur on the shorter list, as this keeps the total
     *       depth of nested calls to less than log_base2(n).
     */
    if ((i - start) < (stop - j)) { /* top list is shorter */
        if ((i - start) > 0)
        mysort(start, i, x, cvec);
        start = j;
    } else {                /* bottom list is shorter */
        if ((stop - j) > 0)
        mysort(j, stop, x, cvec);
        stop = i;
    }
    }
}