neoqs - that adds smallrange support for meanqs
This commit is contained in:
parent
bcc4f3bb62
commit
d80a061240
123
zssort.h
123
zssort.h
@ -1,5 +1,11 @@
|
||||
#ifndef ZS_SORT_H
|
||||
#define ZS_SORT_H
|
||||
|
||||
/** Used in neoqs for applying smallrange heuristics below value-domains of this size */
|
||||
#ifndef NEOQS_SMALLRANGE_TRESHOLD
|
||||
#define NEOQS_SMALLRANGE_TRESHOLD 256
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure:
|
||||
* - ZSSORT: The at most log(n) space needing quicksort
|
||||
@ -268,6 +274,123 @@ static inline void meanqs(uint32_t array[], int low, int high, rpivotstate *stat
|
||||
}
|
||||
}
|
||||
|
||||
/* NEOQS */
|
||||
|
||||
/**
|
||||
* Neoquicksort entry point and outer-recursive function.
|
||||
*
|
||||
* We pick a random pivot, but in the meantime try to quess mean for next level partitioning.
|
||||
* This and neoqs_inner is co-recursive (call each other)
|
||||
* We utilize zsr3_sp2 in case the range is smaller than NEOQS_SMALLRANGE_TRESHOLD.
|
||||
*
|
||||
* @param array The array to sort
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param state The random pivot picking state
|
||||
*/
|
||||
static inline void neoqs(uint32_t array[], int low, int high, rpivotstate *state);
|
||||
|
||||
/**
|
||||
* Inner-recursive function of neoqs - calls neoqs() as next level recursion.
|
||||
*
|
||||
* @param array The array to sort
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param pivotval We first partition to smaller-eq/bigger than pivotval, later we might pick random though
|
||||
* @param state The random pivot picking state
|
||||
*/
|
||||
static inline void neoqs_inter(uint32_t array[], int low, int high, uint32_t pivotval, rpivotstate *state) {
|
||||
|
||||
/* First: partition using pivot val + recurse */
|
||||
|
||||
if (low < high) {
|
||||
/* For the first level, use the pivotval they provide */
|
||||
/* This only helps somewhat, because below loop.... */
|
||||
/* ..But code it better if you can do consistently! */
|
||||
int pi = partition_with_pivotval(array, low, high, pivotval);
|
||||
|
||||
/* If we recurse only the smaller part */
|
||||
/* That ensures at most n/2 elements can */
|
||||
/* be on any given level of the recursion */
|
||||
/* tree: that is we ensure log2(N) memuse! */
|
||||
if((pi - low) < (high - pi)) {
|
||||
// Left smaller: recurse left of pivot
|
||||
neoqs(array, low, pi - 1, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
low = pi + 1;
|
||||
} else {
|
||||
// Right smaller: recurse right of pivot
|
||||
neoqs(array, pi + 1, high, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
high = pi - 1; /* high inclusive! */
|
||||
}
|
||||
}
|
||||
|
||||
/* Later: picking random pivot and partition like that */
|
||||
|
||||
/* (*) Rem.: The above if can be understood as different first iteration of this while loop... */
|
||||
while (low < high) {
|
||||
/* Random picking here - no info anymore about mean */
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
pi = partition_with_pivot(array, pi, low, high);
|
||||
|
||||
/* If we recurse only the smaller part */
|
||||
/* That ensures at most n/2 elements can */
|
||||
/* be on any given level of the recursion */
|
||||
/* tree: that is we ensure log2(N) memuse! */
|
||||
if((pi - low) < (high - pi)) {
|
||||
// Left smaller: recurse left of pivot
|
||||
neoqs(array, low, pi - 1, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
low = pi + 1;
|
||||
} else {
|
||||
// Right smaller: recurse right of pivot
|
||||
neoqs(array, pi + 1, high, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
high = pi - 1; /* high inclusive! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Neoquicksort entry point and outer-recursive function.
|
||||
*
|
||||
* We pick a random pivot, but in the meantime try to guess mean for next level partitioning.
|
||||
* This and neoqs_inner is co-recursive (call each other)
|
||||
* We utilize zsr3_sp2 in case the range is smaller than NEOQS_SMALLRANGE_TRESHOLD.
|
||||
*
|
||||
* @param array The array to sort
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param state The random pivot picking state
|
||||
*/
|
||||
static inline void neoqs(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||
if (low < high) {
|
||||
uint32_t lmin, lmax, rmin, rmax;
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
pi = partition_and_pminmax_with_pivot(array, pi, low, high, &lmin, &lmax, &rmin, &rmax);
|
||||
|
||||
/* These also handle constant (always same valued) subarrays */
|
||||
if(lmin != lmax) {
|
||||
/* Better than (a+b)/2 avg because of overflow possibilities */
|
||||
uint32_t lavg = lmin + (lmax - lmin) / 2;
|
||||
/* Changing to zzsort_rand3_sp2 ensures better smallranges */
|
||||
/* Recursion with inter "ensures" logn stack spacen need! */
|
||||
if(lmax - lmin < NEOQS_SMALLRANGE_TRESHOLD) zssort_rand3_sp2(array, low, pi - 1, state);
|
||||
else neoqs_inter(array, low, pi - 1, lavg, state);
|
||||
}
|
||||
if(rmin != rmax) {
|
||||
/* Better than (a+b)/2 avg because of overflow possibilities */
|
||||
uint32_t ravg = rmin + (rmax - rmin) / 2;
|
||||
/* Changing to zzsort_rand3_sp2 ensures better smallranges */
|
||||
/* Recursion with inter "ensures" logn stack spacen need! */
|
||||
if(rmax - rmin < NEOQS_SMALLRANGE_TRESHOLD) zssort_rand3_sp2(array, pi + 1, high, state);
|
||||
else neoqs_inter(array, pi + 1, high, ravg, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Idea: Quadratic time happens when you repeatedly pick pivots close to the maximum or minimum - so why not re-pick near extremals being picked which now can be cheked? I think we should have a treshold - maybe dynamically set by first minmax - and logarithmically divide the treshold by 2 in case its still too close the next randomization time. This handles smallrange badly though.
|
||||
|
||||
#endif /* ZS_SORT_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user