threeway partitioning inplace quicksort
This commit is contained in:
parent
32b5721e37
commit
a465110170
19
qs.c
19
qs.c
@ -43,7 +43,7 @@ void qsr() {
|
|||||||
printArray(data, n);
|
printArray(data, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// qs test function
|
// zss test function
|
||||||
void zss() {
|
void zss() {
|
||||||
#include "data.inc"
|
#include "data.inc"
|
||||||
|
|
||||||
@ -56,9 +56,26 @@ void zss() {
|
|||||||
printArray(data, n);
|
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() {
|
int main() {
|
||||||
qs();
|
qs();
|
||||||
qsr();
|
qsr();
|
||||||
zss();
|
zss();
|
||||||
|
qs3();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
146
qsort.h
146
qsort.h
@ -10,8 +10,9 @@
|
|||||||
/* Structure:
|
/* Structure:
|
||||||
*
|
*
|
||||||
* - BASICS: Basic quicksort
|
* - BASICS: Basic quicksort
|
||||||
* - EXTRAS: Extra quicksort and partitioning helpers (also random pick and pivot index picks). Basic (free) min-max search
|
* - RANDOMPIV: Randomized pivoting and partitioning by given pivot-indexed element.
|
||||||
* - PMINMAX: Partitioning with min-max searches in generated partitions
|
* - 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!
|
* - VALPART: Partitioning by value - not by random or given pivot index!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -78,7 +79,67 @@ 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);
|
||||||
|
|
||||||
|
/* traverse each element of the array */
|
||||||
|
/* compare them with the pivot */
|
||||||
|
#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;
|
||||||
|
|
||||||
|
/* swap element at i with element at j */
|
||||||
|
swapit(&array[i], &array[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
* Partition the array and using the pivot index
|
||||||
@ -106,6 +167,54 @@ static inline int partition_with_pivot(uint32_t array[], int pi, int low, int hi
|
|||||||
return partition(array, low, high);
|
return partition(array, low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 32-bit LCG for fast random generations
|
||||||
|
static inline uint32_t lcg(uint32_t *state) {
|
||||||
|
*state = *state * 1664525u + 1013904223u;
|
||||||
|
return *state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get pivot index in [0, len-1] without modulus - see our fastrand.h */
|
||||||
|
static inline uint32_t pick_pivot(uint32_t *state, uint32_t len) {
|
||||||
|
uint32_t rand = lcg(state);
|
||||||
|
/* Multiply by len, take the upper 32 bits of the 64-bit result */
|
||||||
|
return (uint32_t)(((uint64_t)rand * len) >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef uint32_t rpivotstate;
|
||||||
|
|
||||||
|
/** Randomized pivoting in-place recursive quicksort on array for elements in [low, high] indices */
|
||||||
|
static inline void quicksort_rand(uint32_t array[], int low, int high, rpivotstate *state) {
|
||||||
|
if (low < high) {
|
||||||
|
int pi = pick_pivot(state, (high + 1) - low) + low;
|
||||||
|
pi = partition_with_pivot(array, pi, low, high);
|
||||||
|
|
||||||
|
/* recursive call on the left of pivot */
|
||||||
|
quicksort_rand(array, low, pi - 1, state);
|
||||||
|
|
||||||
|
/* recursive call on the right of pivot */
|
||||||
|
quicksort_rand(array, pi + 1, high, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
* Partition the array while doing a min-max search and find the pivot element such that
|
||||||
*
|
*
|
||||||
@ -184,35 +293,6 @@ static inline int partition_and_minmax_with_pivot(uint32_t array[], int pi, int
|
|||||||
return partition_and_minmax(array, low, high, minout, maxout);
|
return partition_and_minmax(array, low, high, minout, maxout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 32-bit LCG for fast random generations
|
|
||||||
static inline uint32_t lcg(uint32_t *state) {
|
|
||||||
*state = *state * 1664525u + 1013904223u;
|
|
||||||
return *state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get pivot index in [0, len-1] without modulus - see our fastrand.h */
|
|
||||||
static inline uint32_t pick_pivot(uint32_t *state, uint32_t len) {
|
|
||||||
uint32_t rand = lcg(state);
|
|
||||||
/* Multiply by len, take the upper 32 bits of the 64-bit result */
|
|
||||||
return (uint32_t)(((uint64_t)rand * len) >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef uint32_t rpivotstate;
|
|
||||||
|
|
||||||
/** Randomized pivoting in-place recursive quicksort on array for elements in [low, high] indices */
|
|
||||||
static inline void quicksort_rand(uint32_t array[], int low, int high, rpivotstate *state) {
|
|
||||||
if (low < high) {
|
|
||||||
int pi = pick_pivot(state, (high + 1) - low) + low;
|
|
||||||
pi = partition_with_pivot(array, pi, low, high);
|
|
||||||
|
|
||||||
/* recursive call on the left of pivot */
|
|
||||||
quicksort_rand(array, low, pi - 1, state);
|
|
||||||
|
|
||||||
/* recursive call on the right of pivot */
|
|
||||||
quicksort_rand(array, pi + 1, high, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PMINMAX */
|
/* PMINMAX */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -363,7 +443,7 @@ static inline int partition_with_pivotval(uint32_t array[], int low, int high, u
|
|||||||
swapit(&array[i], &array[j]);
|
swapit(&array[i], &array[j]);
|
||||||
|
|
||||||
/* After this, array[i] can never change - so we can save it as a found pivot-index */
|
/* After this, array[i] can never change - so we can save it as a found pivot-index */
|
||||||
/* Min-search on elements by telling which is closest to pivotval by abs difference! */
|
/* Max-search on elements by telling which is closest to pivotval by abs difference! */
|
||||||
if(array[i] > leftmax) {
|
if(array[i] > leftmax) {
|
||||||
pivoti = i;
|
pivoti = i;
|
||||||
leftmax = array[i];
|
leftmax = array[i];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user