neoqs, meanqs and various quicksort variants

This commit is contained in:
Richard Thier 2025-05-06 03:06:37 +02:00
parent e38a76c0c4
commit 707ab1eb81
2 changed files with 135 additions and 93 deletions

81
qs.c
View File

@ -1,81 +0,0 @@
// gcc qs.c -o qs && ./qs
// Quick sort in C
#include <stdio.h>
// function to swap elements
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
// function to find the partition position
int partition(int array[], int low, int high) {
// select the rightmost element as pivot
int pivot = array[high];
// pointer for greater element
int i = (low - 1);
// traverse each element of the array
// compare them with the pivot
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
swap(&array[i], &array[j]);
}
}
// swap the pivot element with the greater element at i
swap(&array[i + 1], &array[high]);
// return the partition point
return (i + 1);
}
void quickSort(int array[], int low, int high) {
if (low < high) {
// find the pivot element such that
// elements smaller than pivot are on left of pivot
// elements greater than pivot are on right of pivot
int pi = partition(array, low, high);
// recursive call on the left of pivot
quickSort(array, low, pi - 1);
// recursive call on the right of pivot
quickSort(array, pi + 1, high);
}
}
// function to print array elements
void printArray(int array[], int size) {
for (int i = 0; i < size; ++i) {
printf("%d ", array[i]);
}
printf("\n");
}
// main function
int main() {
int data[] = {8, 7, 2, 1, 0, 9, 6};
int n = sizeof(data) / sizeof(data[0]);
printf("Unsorted Array\n");
printArray(data, n);
// perform quicksort on data
quickSort(data, 0, n - 1);
printf("Sorted array in ascending order: \n");
printArray(data, n);
}

143
ypsu.cpp
View File

@ -16,6 +16,9 @@
#include "ska_sort.hpp"
#include "gptsort.h"
#include "thiersort.h"
#include "qsort/qsort.h"
#include "qsort/zssort.h"
#include "qsort/chatgpt_qs.h"
// #define MAGYAR_SORT_DEFAULT_REUSE
#include "magyarsort.h"
@ -41,8 +44,8 @@ std::vector<std::string> inputtypes = {
"ascdesc",
"descasc",
"descdesc",
"rand",
"smallrange",
"rand",
};
std::vector<uint32_t> geninput(const std::string &type, int n) {
std::vector<uint32_t> v(n);
@ -121,7 +124,80 @@ void twopass(uint32_t *a, int n) {
free(buf);
}
// TODO: zssort (quicksort jobbítás)
/** "Standardly" written inplace recursive quicksort */
static inline void do_qsort(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
quicksort(a, 0, n - 1);
}
static inline void do_qsr3(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
quicksort_rand3(a, 0, n - 1, &state);
}
/** Quicksort with fast random pivoting */
static inline void do_qsr(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
quicksort_rand(a, 0, n - 1, &state);
}
/** Zsolti's quicksort version with at most O(log(n)) memuse because loop instead half of the recursions */
static inline void do_zsssort(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
zssort(a, 0, n - 1);
}
/** Fastrandomized zss */
static inline void do_zsr(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
zssort_rand(a, 0, n - 1, &state);
}
/** Fastrandomized zss3 */
static inline void do_zsr3(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
zssort_rand3(a, 0, n - 1, &state);
}
/** Fastrandomized zss3 single-pass threewayed */
static inline void do_zsr3_sp(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
zssort_rand3_sp(a, 0, n - 1, &state);
}
/** Fastrandomized zss3 single-pass threewayed */
static inline void do_zsr3_sp2(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
zssort_rand3_sp2(a, 0, n - 1, &state);
}
/** Fastrandomized zss with const input check */
static inline void do_zsrc(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
zsrc(a, 0, n - 1, &state);
}
/** meanqs */
static inline void do_meanqs(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
meanqs(a, 0, n - 1, &state);
}
/** neoqs */
static inline void do_neoqs(uint32_t *a, int n) noexcept {
assert(n * uint32_t(sizeof(a[0])) <= INT_MAX);
rpivotstate state;
neoqs(a, 0, n - 1, &state);
}
// mormord — Today at 2:27 AM
// 1 2 2 2 3
@ -287,7 +363,7 @@ static inline void mormord_sort_impl(uint32_t *a, int n) noexcept {
/* Pivot 2 */
uint32_t radixval2 = morgrab<j>(a[pivoti2]);
uint32_t targeti2 = --radics2[radixval2]; // dec index (!)
uint32_t targeti2 = boundz.second + (--radics2[radixval2]); // dec index (!)
// Bitmask: true -> 11.....1; false -> 00.....0
uint32_t mask2 = ~((targeti2 > pivoti2) - 1);
@ -327,7 +403,7 @@ static inline void mormord_sort_impl(uint32_t *a, int n) noexcept {
/* Pivot 2+ */
uint32_t radixval2 = morgrab<j>(a[pivoti2]);
uint32_t targeti2 = --radics2[radixval2]; // dec index (!)
uint32_t targeti2 = boundz.second + (--radics2[radixval2]); // dec index (!)
// Bitmask: true -> 11.....1; false -> 00.....0
uint32_t mask2 = ~((targeti2 > pivoti2) - 1);
@ -764,12 +840,14 @@ void measure_single(int n) {
int main(void) {
//int n = 100000000;
//int n = 10000000;
//int n = 1000000;
int n = 1000000;
//int n = 100000;
//int n = 10000;
//int n = 20000;
//int n = 1000;
int n = 200;
//int n = 200;
//int n = 170;
//int n = 100;
//int n = 180;
//int n = 10;
printf("Sorting %d elements:\n\n", n);
@ -780,15 +858,18 @@ int main(void) {
for (auto inputtype : inputtypes) {
printf("%10s", inputtype.c_str());
// fflush(stdout); // XXX: FIXME?
// fflush(stdout);
std::vector<uint32_t> v(n), w(n), expected(n);
v = geninput(inputtype, n);
measure(inputtype, "copy", [&] { w = v; });
w = v;
measure(inputtype, "std", [&] { std::sort(std::begin(w), std::end(w)); });
expected = w;
/*
w = v;
measure(inputtype, "ska", [&] { ska_sort(std::begin(w), std::end(w)); });
*/
w = v;
measure(inputtype, "ska_copy", [&] {
std::vector<uint32_t> buf(w.size());
@ -801,10 +882,11 @@ int main(void) {
measure(inputtype, "magyar", [&] { MagyarSort::sort<uint32_t>(&w[0], w.size()); });
assert(w == expected);
*/
/*
w = v;
measure(inputtype, "mormord", [&] { mormord_sort(&w[0], w.size()); });
assert(w == expected);
/*
w = v;
measure(inputtype, "2pass", [&] { twopass(&w[0], w.size()); });
@ -823,10 +905,51 @@ int main(void) {
assert(w == expected);
w = v;
measure(inputtype, "sp", [&] { spsort(&w[0], w.size()); });
assert(w == expected);*/
assert(w == expected);
w = v;
measure(inputtype, "gptbuck", [&] { gpt_bucket_sort(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "gpt_qsort", [&] { gpt_quicksort(w); });
assert(w == expected);
w = v;
measure(inputtype, "qsort", [&] { do_qsort(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "zssort", [&] { do_zsssort(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "qsr", [&] { do_qsr(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "zsr", [&] { do_zsr(&w[0], w.size()); });
assert(w == expected);
*/
w = v;
measure(inputtype, "qsr3", [&] { do_qsr3(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "zsr3", [&] { do_zsr3(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "zsr3_sp", [&] { do_zsr3_sp(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "zsr3_sp2", [&] { do_zsr3_sp2(&w[0], w.size()); });
assert(w == expected);
/*
w = v;
measure(inputtype, "zsrc", [&] { do_zsrc(&w[0], w.size()); });
assert(w == expected);
*/
w = v;
measure(inputtype, "meanqs", [&] { do_meanqs(&w[0], w.size()); });
assert(w == expected);
w = v;
measure(inputtype, "neoqs", [&] { do_neoqs(&w[0], w.size()); });
assert(w == expected);
/*
w = v;
measure(inputtype, "magbuck", [&] { magyar_bucket_sort(&w[0], w.size()); });