/* * 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; } } }