Compare commits
10 Commits
6fd6dbfff3
...
12d30a588a
Author | SHA1 | Date | |
---|---|---|---|
|
12d30a588a | ||
|
cebc516125 | ||
|
bc500c84e8 | ||
|
a465110170 | ||
|
32b5721e37 | ||
|
37ed6c4f59 | ||
|
69adbe4ae9 | ||
|
22bb267000 | ||
|
04705b5790 | ||
|
f15cc423d2 |
17
chatgpt_qs.cpp
Normal file
17
chatgpt_qs.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "chatgpt_qs.h"
|
||||
|
||||
// Example usage
|
||||
int main() {
|
||||
std::vector<uint32_t> arr = {3, 6, 8, 10, 1, 2, 1};
|
||||
std::vector<uint32_t> sorted = gpt_quicksort(arr);
|
||||
|
||||
for (uint32_t num : sorted) {
|
||||
std::cout << num << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
37
chatgpt_qs.h
Normal file
37
chatgpt_qs.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef CHATGPT_QS_H
|
||||
#define CHATGPT_QS_H
|
||||
|
||||
std::vector<uint32_t> gpt_quicksort(const std::vector<uint32_t> &arr) {
|
||||
if (arr.size() <= 1) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
uint32_t pivot = arr[arr.size() / 2];
|
||||
std::vector<uint32_t> left;
|
||||
std::vector<uint32_t> middle;
|
||||
std::vector<uint32_t> right;
|
||||
|
||||
for (uint32_t x : arr) {
|
||||
if (x < pivot) {
|
||||
left.push_back(x);
|
||||
} else if (x == pivot) {
|
||||
middle.push_back(x);
|
||||
} else {
|
||||
right.push_back(x);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> sorted_left = gpt_quicksort(left);
|
||||
std::vector<uint32_t> sorted_right = gpt_quicksort(right);
|
||||
|
||||
// Concatenate sorted_left + middle + sorted_right
|
||||
std::vector<uint32_t> result;
|
||||
result.reserve(sorted_left.size() + middle.size() + sorted_right.size());
|
||||
result.insert(result.end(), sorted_left.begin(), sorted_left.end());
|
||||
result.insert(result.end(), middle.begin(), middle.end());
|
||||
result.insert(result.end(), sorted_right.begin(), sorted_right.end());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // CHATGPT_QS_H
|
19
qs.c
19
qs.c
@ -43,7 +43,7 @@ void qsr() {
|
||||
printArray(data, n);
|
||||
}
|
||||
|
||||
// qs test function
|
||||
// zss test function
|
||||
void zss() {
|
||||
#include "data.inc"
|
||||
|
||||
@ -56,9 +56,26 @@ void zss() {
|
||||
printArray(data, n);
|
||||
}
|
||||
|
||||
// qs3 test function
|
||||
void qs3() {
|
||||
#include "data.inc"
|
||||
|
||||
int n = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
// memory junnnk is enough
|
||||
rpivotstate rand;
|
||||
|
||||
// perform qs3 on data
|
||||
quicksort_rand3(data, 0, n - 1, &rand);
|
||||
|
||||
printf("(qs3) Sorted array in ascending order: \n");
|
||||
printArray(data, n);
|
||||
}
|
||||
|
||||
int main() {
|
||||
qs();
|
||||
qsr();
|
||||
zss();
|
||||
qs3();
|
||||
return 0;
|
||||
}
|
||||
|
352
qsort.h
352
qsort.h
@ -4,10 +4,16 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Uncomment for debugging with if(someevent) raise(SIGINT); */
|
||||
#include <signal.h>
|
||||
|
||||
/* Structure:
|
||||
*
|
||||
* - BASICS
|
||||
* - EXTRAS
|
||||
* - BASICS: Basic quicksort
|
||||
* - RANDOMPIV: Randomized pivoting and partitioning by given pivot-indexed element.
|
||||
* - MINMAX: partitioning while doing min-max over the whole + related extras.
|
||||
* - PMINMAX: Partitioning with min-max searches in generated partitions + related.
|
||||
* - VALPART: Partitioning by value - not by random or given pivot index!
|
||||
*/
|
||||
|
||||
/* BASICS */
|
||||
@ -28,6 +34,7 @@ static inline void swapit(uint32_t *a, uint32_t *b) {
|
||||
* @param array The array to partition
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition(uint32_t array[], int low, int high) {
|
||||
/* This is "Lomuto"s unidirectional partitioner - see algorithms book */
|
||||
@ -43,7 +50,6 @@ static inline int partition(uint32_t array[], int low, int high) {
|
||||
#pragma GCC unroll 4
|
||||
for (int j = low; j < high; ++j) {
|
||||
if (array[j] <= pivot) {
|
||||
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
++i;
|
||||
@ -73,7 +79,79 @@ static inline void quicksort(uint32_t array[], int low, int high) {
|
||||
}
|
||||
}
|
||||
|
||||
/* EXTRAS */
|
||||
/* THREEWAY */
|
||||
|
||||
struct pret3 {
|
||||
int leftend;
|
||||
int rightend;
|
||||
};
|
||||
typedef struct pret3 pret3;
|
||||
|
||||
/**
|
||||
* Partition the array threeway by puutting ALL pivots to the middle and smaller/biggers left-right
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param pivotval This value is used to partition the array.
|
||||
* @returns The partition points, end of left and right (inclusive)
|
||||
*/
|
||||
static inline pret3 partition3(uint32_t array[], int low, int high, uint32_t pivotval) {
|
||||
/* select the rightmost element as pivot */
|
||||
uint32_t pivot = pivotval;
|
||||
|
||||
/* index until smaller or eq elements lay */
|
||||
int i = (low - 1);
|
||||
uint32_t pc = 0;
|
||||
|
||||
/* traverse each element of the array */
|
||||
/* compare them with the pivot */
|
||||
#pragma GCC unroll 4
|
||||
for (int j = low; j <= high; ++j) {
|
||||
/* Branchless pivot-count */
|
||||
pc += (array[j] == pivot);
|
||||
|
||||
if(array[j] < pivot) {
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
++i;
|
||||
|
||||
/* swap element at i with element at j */
|
||||
swapit(&array[i], &array[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Can spare out the second loop in these cases */
|
||||
if(pc < 2) {
|
||||
pret3 ret;
|
||||
ret.leftend = i;
|
||||
ret.rightend = i + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* index until smaller or eq elements lay */
|
||||
int i2 = (high + 1);
|
||||
|
||||
#pragma GCC unroll 4
|
||||
for (int j = high; j > i; --j) {
|
||||
if (array[j] > pivot) {
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
--i2;
|
||||
|
||||
/* swap element at i with element at j */
|
||||
swapit(&array[i2], &array[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* return the partition points */
|
||||
pret3 ret;
|
||||
ret.leftend = i;
|
||||
ret.rightend = i2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* RANDOMPIV */
|
||||
|
||||
/**
|
||||
* Partition the array and using the pivot index
|
||||
@ -85,6 +163,7 @@ static inline void quicksort(uint32_t array[], int low, int high) {
|
||||
* @param pi The index of the pivot element to use. 0 or high is what OG quicksorts do.
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_with_pivot(uint32_t array[], int pi, int low, int high) {
|
||||
/*
|
||||
@ -129,4 +208,269 @@ static inline void quicksort_rand(uint32_t array[], int low, int high, rpivotsta
|
||||
}
|
||||
}
|
||||
|
||||
/* THREEWAY_RAND */
|
||||
|
||||
/** Randomized pivoting in-place recursive quicksort on array for elements in [low, high] indices */
|
||||
static inline void quicksort_rand3(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||
if (low < high) {
|
||||
/* partition threeway by random pivot */
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
pret3 res = partition3(array, low, high, array[pi]);
|
||||
|
||||
/* recursive call on the left of pivot */
|
||||
quicksort_rand3(array, low, res.leftend, state);
|
||||
|
||||
/* recursive call on the right of pivot */
|
||||
quicksort_rand3(array, res.rightend, high, state);
|
||||
}
|
||||
}
|
||||
|
||||
/* MINMAX */
|
||||
|
||||
/**
|
||||
* Partition the array while doing a min-max search and find the pivot element such that
|
||||
*
|
||||
* - Elements smaller than pivot are on left of pivot
|
||||
* - Elements greater than pivot are on right of pivot
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param minout OUT: Will be filled with the minimum key
|
||||
* @param maxout OUT: Will be filled with the maximum key
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_and_minmax(uint32_t array[], int low, int high, uint32_t *minout, uint32_t *maxout) {
|
||||
/* This is "Lomuto"s unidirectional partitioner - see algorithms book */
|
||||
|
||||
/* select the rightmost element as pivot */
|
||||
uint32_t pivot = array[high];
|
||||
*minout = pivot;
|
||||
*maxout = pivot;
|
||||
|
||||
/* index until smaller or eq elements lay */
|
||||
int i = (low - 1);
|
||||
|
||||
/* traverse each element of the array */
|
||||
/* compare them with the pivot */
|
||||
#pragma GCC unroll 4
|
||||
for (int j = low; j < high; ++j) {
|
||||
/* Branchless min-max */
|
||||
*minout = array[j] < *minout ? array[j] : *minout;
|
||||
*maxout = array[j] > *maxout ? array[j] : *maxout;
|
||||
|
||||
/* Lomuto partitioning */
|
||||
if (array[j] <= pivot) {
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
++i;
|
||||
|
||||
/* swap element at i with element at j */
|
||||
swapit(&array[i], &array[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* swap the pivot element with the greater element at i */
|
||||
swapit(&array[i + 1], &array[high]);
|
||||
|
||||
/* return the partition point */
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition the array and min-max and using the pivot index
|
||||
*
|
||||
* - Elements smaller than pivot are on left of pivot
|
||||
* - Elements greater than pivot are on right of pivot
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param pi The index of the pivot element to use. 0 or high is what OG quicksorts do.
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param minout OUT: Will be filled with the minimum key
|
||||
* @param maxout OUT: Will be filled with the maximum key
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_and_minmax_with_pivot(uint32_t array[], int pi, int low, int high, uint32_t *minout, uint32_t *maxout) {
|
||||
/*
|
||||
* Rem.: This looks like overhead,
|
||||
* but after seriously considering
|
||||
* writing the whole out I can tell
|
||||
* this is still fastests basically.
|
||||
*/
|
||||
|
||||
/* swap pivot with rightmost */
|
||||
swapit(&array[high], &array[pi]);
|
||||
/* delegate to previous sol. */
|
||||
return partition_and_minmax(array, low, high, minout, maxout);
|
||||
}
|
||||
|
||||
/* PMINMAX */
|
||||
|
||||
/**
|
||||
* Partition the array with partition-based min-max search (4 values: 2 per partition) and find the pivot element such that
|
||||
*
|
||||
* - Elements smaller than pivot are on left of pivot
|
||||
* - Elements greater than pivot are on right of pivot
|
||||
*
|
||||
* (***): The left min-max outputs can return not just the left partition, but left partition ++ pivotpoint region min-max!
|
||||
* This does not only happen if partition is empty, but also when pivot was already highest and last earlier.
|
||||
* Would be hard to handle this edge-case and min-max out is generally used as output hints only so I prefer speed..
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param minout_left OUT: Will be filled with the minimum key of left partition or pivot value when partition empty. Also (***)
|
||||
* @param maxout_left OUT: Will be filled with the maximum key of left partition or pivot value when partition empty. Also (***)
|
||||
* @param minout_right OUT: Will be filled with the minimum key of right partition or pivot value when partition empty
|
||||
* @param maxout_right OUT: Will be filled with the maximum key of right partition or pivot value when partition empty
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_and_pminmax(
|
||||
uint32_t array[],
|
||||
int low,
|
||||
int high,
|
||||
uint32_t *minout_left,
|
||||
uint32_t *maxout_left,
|
||||
uint32_t *minout_right,
|
||||
uint32_t *maxout_right) {
|
||||
/* This is "Lomuto"s unidirectional partitioner - see algorithms book */
|
||||
|
||||
/* select the rightmost element as pivot */
|
||||
uint32_t pivot = array[high];
|
||||
*minout_left = pivot;
|
||||
*maxout_left = pivot;
|
||||
*minout_right = pivot;
|
||||
*maxout_right = pivot;
|
||||
|
||||
/* index until smaller or eq elements lay */
|
||||
int i = (low - 1);
|
||||
|
||||
/* traverse each element of the array */
|
||||
/* compare them with the pivot */
|
||||
#pragma GCC unroll 4
|
||||
for (int j = low; j < high; ++j) {
|
||||
/* Lomuto partitioning */
|
||||
if (array[j] <= pivot) {
|
||||
/* Branchless min-max */
|
||||
*minout_left = array[j] < *minout_left ? array[j] : *minout_left;
|
||||
*maxout_left = array[j] > *maxout_left ? array[j] : *maxout_left;
|
||||
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
++i;
|
||||
|
||||
/* swap element at i with element at j */
|
||||
swapit(&array[i], &array[j]);
|
||||
} else {
|
||||
/* Branchless min-max */
|
||||
*minout_right = array[j] < *minout_right ? array[j] : *minout_right;
|
||||
*maxout_right = array[j] > *maxout_right ? array[j] : *maxout_right;
|
||||
}
|
||||
}
|
||||
|
||||
/* swap the pivot element with the greater element at i */
|
||||
swapit(&array[i + 1], &array[high]);
|
||||
|
||||
/* return the partition point */
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition the array with partition-based min-max search (4 values: 2 per partition) and using the pivot index
|
||||
*
|
||||
* - Elements smaller than pivot are on left of pivot
|
||||
* - Elements greater than pivot are on right of pivot
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param pi The index of the pivot element to use. 0 or high is what OG quicksorts do.
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param minout OUT: Will be filled with the minimum key
|
||||
* @param maxout OUT: Will be filled with the maximum key
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_and_pminmax_with_pivot(
|
||||
uint32_t array[],
|
||||
int pi,
|
||||
int low,
|
||||
int high,
|
||||
uint32_t *minout_left,
|
||||
uint32_t *maxout_left,
|
||||
uint32_t *minout_right,
|
||||
uint32_t *maxout_right) {
|
||||
/*
|
||||
* Rem.: This looks like overhead,
|
||||
* but after seriously considering
|
||||
* writing the whole out I can tell
|
||||
* this is still fastests basically.
|
||||
*/
|
||||
|
||||
/* swap pivot with rightmost */
|
||||
swapit(&array[high], &array[pi]);
|
||||
/* delegate to previous sol. */
|
||||
return partition_and_pminmax(array, low, high, minout_left, maxout_left, minout_right, maxout_right);
|
||||
}
|
||||
|
||||
/* VALPART */
|
||||
|
||||
/**
|
||||
* Partition the array using pivot value - and find pivot closest to that value (and place them at proper pivot index)
|
||||
*
|
||||
* - Elements smaller-eq than pivotval are on left of pivot
|
||||
* - Elements greater than pivotval are on right of pivot
|
||||
* - The "pivot" element we find is the biggest among the ones smaller-eq to the pivot value
|
||||
* or if there is no such (all is greater) we return first greater-than value index (right[0])
|
||||
*
|
||||
* @param array The array to partition
|
||||
* @param low From when. (inclusive)
|
||||
* @param high Until when. (inclusive too!)
|
||||
* @param pivotval This value is used to partition the array.
|
||||
* @returns The partition point.
|
||||
*/
|
||||
static inline int partition_with_pivotval(uint32_t array[], int low, int high, uint32_t pivotval) {
|
||||
/* This is "Lomuto"s unidirectional partitioner - see algorithms book */
|
||||
|
||||
/* Select the rightmost element as pivot just because */
|
||||
/* Need some start-value for min(abs(pv - p)) search! */
|
||||
int64_t leftmax = -1;
|
||||
/* Index of currently found pivot value */
|
||||
uint32_t pivoti = low;
|
||||
|
||||
/* index until smaller or eq elements lay */
|
||||
int i = (low - 1);
|
||||
|
||||
/* traverse each element of the array */
|
||||
/* compare them with the pivotval */
|
||||
/* The "<=" is needed for our trickz here too */
|
||||
#pragma GCC unroll 4
|
||||
for (int j = low; j <= high; ++j) {
|
||||
/* This "<=" ensures pivoti must be only searched among "left" values! */
|
||||
if (array[j] <= pivotval) {
|
||||
/* if element smaller than pivot is found */
|
||||
/* swap it with the greater element pointed by i */
|
||||
++i;
|
||||
|
||||
/* swap element at i with element at j */
|
||||
swapit(&array[i], &array[j]);
|
||||
|
||||
/* After this, array[i] can never change - so we can save it as a found pivot-index */
|
||||
/* Max-search on elements by telling which is closest to pivotval by abs difference! */
|
||||
if(array[i] > leftmax) {
|
||||
pivoti = i;
|
||||
leftmax = array[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Must check if above loop found elem at all - because its guessing */
|
||||
if(i != (low - 1)) {
|
||||
/* swap the pivot element into its place */
|
||||
swapit(&array[i], &array[pivoti]);
|
||||
}
|
||||
|
||||
/* return the partition point: index of pivot element */
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* MY_QUICKSORT_H */
|
||||
|
167
zssort.h
167
zssort.h
@ -1,9 +1,19 @@
|
||||
#ifndef ZS_SORT_H
|
||||
#define ZS_SORT_H
|
||||
/*
|
||||
* Structure:
|
||||
* - ZSSORT: The at most log(n) space needing quicksort
|
||||
* - RZSSORT: Randomized pivoting variant at most log(n) space needing quicksort
|
||||
* - RZSSORTC: Added check for fully same value const array (also randomized pivot)
|
||||
* - MEANQS: Randomized pivoting AND pivoting based on min-max range - dual recursive
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qsort.h"
|
||||
|
||||
/* ZSSORT */
|
||||
|
||||
/** Always at most log(n) space needing quicksort variant */
|
||||
static inline void zssort(uint32_t array[], int low, int high) {
|
||||
/* (*) Loop handles original "other half recursion"! */
|
||||
while(low < high) {
|
||||
@ -27,6 +37,9 @@ static inline void zssort(uint32_t array[], int low, int high) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSSORTR */
|
||||
|
||||
/** Always at most log(n) space needing randomized quicksort variant */
|
||||
static inline void zssort_rand(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||
while (low < high) {
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
@ -50,4 +63,158 @@ static inline void zssort_rand(uint32_t array[], int low, int high, rpivotstate
|
||||
}
|
||||
}
|
||||
|
||||
/* THREEWAY_ZS */
|
||||
|
||||
/** Always at most log(n) space needing randomized quicksort variant */
|
||||
static inline void zssort_rand3(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||
while (low < high) {
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
pret3 res = partition3(array, low, high, array[pi]);
|
||||
|
||||
/* 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((res.leftend - low) < (high - res.rightend)) {
|
||||
// Left smaller: recurse left of pivot
|
||||
zssort_rand3(array, low, res.leftend, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
low = res.rightend;
|
||||
} else {
|
||||
// Right smaller: recurse right of pivot
|
||||
zssort_rand3(array, res.rightend, high, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
high = res.leftend; /* high inclusive! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSSORTC */
|
||||
|
||||
/** Always at most log(n) space needing randomized quicksort variant - with checking for sameconst-arrays */
|
||||
static inline void zsrc(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||
if (low < high) {
|
||||
uint32_t min, max;
|
||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||
pi = partition_and_minmax_with_pivot(array, pi, low, high, &min, &max);
|
||||
if(min != max) {
|
||||
/* Recursion with zssort_rand ensures logn+1 stack spacen need! */
|
||||
zssort_rand(array, low, pi - 1, state);
|
||||
zssort_rand(array, pi + 1, high, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MEANQS */
|
||||
|
||||
/**
|
||||
* Rangsort entry point and outer-recursive function of meanqs.
|
||||
*
|
||||
* We pick a random pivot, but in the meantime try to quess mean for next level partitioning.
|
||||
* This and meanqs_inner is co-recursive (call each other)
|
||||
*
|
||||
* @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 meanqs(uint32_t array[], int low, int high, rpivotstate *state);
|
||||
|
||||
/**
|
||||
* Inner-recursive function of meanqs - calls meanqs() 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 meanqs_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
|
||||
meanqs(array, low, pi - 1, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
low = pi + 1;
|
||||
} else {
|
||||
// Right smaller: recurse right of pivot
|
||||
meanqs(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
|
||||
meanqs(array, low, pi - 1, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
low = pi + 1;
|
||||
} else {
|
||||
// Right smaller: recurse right of pivot
|
||||
meanqs(array, pi + 1, high, state);
|
||||
// (*) Update partitioning loop for remaining part
|
||||
high = pi - 1; /* high inclusive! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rangsort entry point and outer-recursive function of meanqs.
|
||||
*
|
||||
* We pick a random pivot, but in the meantime try to quess mean for next level partitioning.
|
||||
* This and meanqs_inner is co-recursive (call each other)
|
||||
*
|
||||
* @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 meanqs(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;
|
||||
/* Recursion with inter "ensures" logn stack spacen need! */
|
||||
meanqs_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;
|
||||
/* Recursion with inter "ensures" logn stack spacen need! */
|
||||
meanqs_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