#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int int_compar(const void *a, const void *b) {
// Cast pointers to integers
int int_a = *(const int *)a;
int int_b = *(const int *)b;
// Return comparison result without overflow
if (int_a < int_b) {
return -1;
} else if (int_a > int_b) {
return 1;
} else {
return 0;
}
}
void quicksort_internal(void *base, size_t size, size_t start, size_t end, int (*compar)(const void *, const void *)) {
// Base case: If the range is invalid or trivially sorted
if (start >= end - 1 || end == 0) {
return;
}
// Treat base as a byte array for pointer arithmetic
uint8_t *array = (uint8_t *)base;
// Choosing a pivot: Set pivot as the last element in the range
size_t pivot = end - 1;
// Randomly select a "swapper" index within the range and swap it with the pivot
size_t swapper
= start
+ rand() % (end
- start
); if (swapper != pivot) {
uint8_t temp[size];
memcpy(temp
, array
+ swapper
* size
, size
); memcpy(array
+ swapper
* size
, array
+ pivot
* size
, size
); memcpy(array
+ pivot
* size
, temp
, size
); }
// Partitioning
size_t swappoint = start; // Tracks the position of smaller elements
for (size_t examinepoint = start; examinepoint < pivot; examinepoint++) {
if (compar(array + examinepoint * size, array + pivot * size) < 0) {
// Swap element at examinepoint with element at swappoint
uint8_t temp[size];
memcpy(temp
, array
+ examinepoint
* size
, size
); memcpy(array
+ examinepoint
* size
, array
+ swappoint
* size
, size
); memcpy(array
+ swappoint
* size
, temp
, size
); swappoint++;
}
}
// Place the pivot in its correct position by swapping with the swappoint
if (swappoint != pivot) {
uint8_t temp[size];
memcpy(temp
, array
+ pivot
* size
, size
); memcpy(array
+ pivot
* size
, array
+ swappoint
* size
, size
); memcpy(array
+ swappoint
* size
, temp
, size
); }
// Recursive sorting of the left and right partitions
quicksort_internal(base, size, start, swappoint, compar); // Left partition
quicksort_internal(base, size, swappoint + 1, end, compar); // Right partition
}
// This is the exact same format as qsort, but you
// must NOT use qsort to implement this.
// You probably want to create a quicksort_internal function that
// you call in order to properly implement quicksort.
void quicksort_c(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
{
if (!base || size == 0 || nmemb <= 1 || !compar) {
return;
}
uint8_t *array = (uint8_t *)base;
bool is_sorted = true; // Assume the array is sorted unless proven otherwise
// Check if the array is pre-sorted or all-same
for (size_t i = 1; i < nmemb; i++) {
if (compar(array + (i - 1) * size, array + i * size) > 0) {
is_sorted = false; // Found an unsorted pair
break;
}
}
// If the array is not sorted, proceed with quicksort
if (!is_sorted) {
quicksort_internal(base, size, 0, nmemb, compar);
} else {
printf("Array is already sorted. Skipping quicksort.\n"); }
}
int main() {
// Seed for randomness
int data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // Reverse-sorted data
size_t nmemb = sizeof(data) / sizeof(data[0]);
quicksort_c(data, nmemb, sizeof(int), int_compar);
// Print sorted array
for (size_t i = 0; i < nmemb; i++) {
}
printf("\nPathological pre-sorted test\n"); nmemb=10000;
int sorted_data[nmemb];
for (size_t i = 0; i < nmemb; i++) {
sorted_data[i] = i;
}
clock_t start_time
= clock(); quicksort_c(sorted_data, nmemb, sizeof(int), int_compar);
clock_t stop_time
= clock(); double total_time = (double)(stop_time - start_time) / CLOCKS_PER_SEC * 1e6; // in microseconds
printf("Pathological pre-sorted time: %.2f microseconds\n", total_time
);
printf("\nPathological all-equal test\n"); int equal_data[nmemb];
for (size_t i = 0; i < nmemb; i++) {
equal_data[i] = 42;
}
quicksort_c(equal_data, nmemb, sizeof(int), int_compar);
total_time = (double)(stop_time - start_time) / CLOCKS_PER_SEC * 1e6; // in microseconds
printf("Pathological all-equal time: %.2f microseconds\n", total_time
);
printf("\nRandomized test\n"); int random_data[nmemb];
for (size_t i = 0; i < nmemb; i++) {
random_data
[i
] = rand() % 1000; }
quicksort_c(random_data, nmemb, sizeof(int), int_compar);
total_time = (double)(stop_time - start_time) / CLOCKS_PER_SEC * 1e6; // in microseconds
printf("Randomized time: %.2f microseconds\n", total_time
);
return 0;
}
I2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGRlZi5oPgojaW5jbHVkZSA8c3RkaW50Lmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHRpbWUuaD4KCmludCBpbnRfY29tcGFyKGNvbnN0IHZvaWQgKmEsIGNvbnN0IHZvaWQgKmIpIHsKICAgIC8vIENhc3QgcG9pbnRlcnMgdG8gaW50ZWdlcnMKICAgIGludCBpbnRfYSA9ICooY29uc3QgaW50ICopYTsKICAgIGludCBpbnRfYiA9ICooY29uc3QgaW50ICopYjsKCiAgICAvLyBSZXR1cm4gY29tcGFyaXNvbiByZXN1bHQgd2l0aG91dCBvdmVyZmxvdwogICAgaWYgKGludF9hIDwgaW50X2IpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICB9IGVsc2UgaWYgKGludF9hID4gaW50X2IpIHsKICAgICAgICByZXR1cm4gMTsKICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9Cn0KCnZvaWQgcXVpY2tzb3J0X2ludGVybmFsKHZvaWQgKmJhc2UsIHNpemVfdCBzaXplLCBzaXplX3Qgc3RhcnQsIHNpemVfdCBlbmQsIGludCAoKmNvbXBhcikoY29uc3Qgdm9pZCAqLCBjb25zdCB2b2lkICopKSB7CiAgICAvLyBCYXNlIGNhc2U6IElmIHRoZSByYW5nZSBpcyBpbnZhbGlkIG9yIHRyaXZpYWxseSBzb3J0ZWQKICAgIGlmIChzdGFydCA+PSBlbmQgLSAxIHx8IGVuZCA9PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIFRyZWF0IGJhc2UgYXMgYSBieXRlIGFycmF5IGZvciBwb2ludGVyIGFyaXRobWV0aWMKICAgIHVpbnQ4X3QgKmFycmF5ID0gKHVpbnQ4X3QgKiliYXNlOwoKICAgIC8vIENob29zaW5nIGEgcGl2b3Q6IFNldCBwaXZvdCBhcyB0aGUgbGFzdCBlbGVtZW50IGluIHRoZSByYW5nZQogICAgc2l6ZV90IHBpdm90ID0gZW5kIC0gMTsKCiAgICAvLyBSYW5kb21seSBzZWxlY3QgYSAic3dhcHBlciIgaW5kZXggd2l0aGluIHRoZSByYW5nZSBhbmQgc3dhcCBpdCB3aXRoIHRoZSBwaXZvdAogICAgc2l6ZV90IHN3YXBwZXIgPSBzdGFydCArIHJhbmQoKSAlIChlbmQgLSBzdGFydCk7CiAgICBpZiAoc3dhcHBlciAhPSBwaXZvdCkgewogICAgICAgIHVpbnQ4X3QgdGVtcFtzaXplXTsKICAgICAgICBtZW1jcHkodGVtcCwgYXJyYXkgKyBzd2FwcGVyICogc2l6ZSwgc2l6ZSk7CiAgICAgICAgbWVtY3B5KGFycmF5ICsgc3dhcHBlciAqIHNpemUsIGFycmF5ICsgcGl2b3QgKiBzaXplLCBzaXplKTsKICAgICAgICBtZW1jcHkoYXJyYXkgKyBwaXZvdCAqIHNpemUsIHRlbXAsIHNpemUpOwogICAgfQoKICAgIC8vIFBhcnRpdGlvbmluZwogICAgc2l6ZV90IHN3YXBwb2ludCA9IHN0YXJ0OyAvLyBUcmFja3MgdGhlIHBvc2l0aW9uIG9mIHNtYWxsZXIgZWxlbWVudHMKICAgIGZvciAoc2l6ZV90IGV4YW1pbmVwb2ludCA9IHN0YXJ0OyBleGFtaW5lcG9pbnQgPCBwaXZvdDsgZXhhbWluZXBvaW50KyspIHsKICAgICAgICBpZiAoY29tcGFyKGFycmF5ICsgZXhhbWluZXBvaW50ICogc2l6ZSwgYXJyYXkgKyBwaXZvdCAqIHNpemUpIDwgMCkgewogICAgICAgICAgICAvLyBTd2FwIGVsZW1lbnQgYXQgZXhhbWluZXBvaW50IHdpdGggZWxlbWVudCBhdCBzd2FwcG9pbnQKICAgICAgICAgICAgdWludDhfdCB0ZW1wW3NpemVdOwogICAgICAgICAgICBtZW1jcHkodGVtcCwgYXJyYXkgKyBleGFtaW5lcG9pbnQgKiBzaXplLCBzaXplKTsKICAgICAgICAgICAgbWVtY3B5KGFycmF5ICsgZXhhbWluZXBvaW50ICogc2l6ZSwgYXJyYXkgKyBzd2FwcG9pbnQgKiBzaXplLCBzaXplKTsKICAgICAgICAgICAgbWVtY3B5KGFycmF5ICsgc3dhcHBvaW50ICogc2l6ZSwgdGVtcCwgc2l6ZSk7CiAgICAgICAgICAgIHN3YXBwb2ludCsrOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBQbGFjZSB0aGUgcGl2b3QgaW4gaXRzIGNvcnJlY3QgcG9zaXRpb24gYnkgc3dhcHBpbmcgd2l0aCB0aGUgc3dhcHBvaW50CiAgICBpZiAoc3dhcHBvaW50ICE9IHBpdm90KSB7CiAgICAgICAgdWludDhfdCB0ZW1wW3NpemVdOwogICAgICAgIG1lbWNweSh0ZW1wLCBhcnJheSArIHBpdm90ICogc2l6ZSwgc2l6ZSk7CiAgICAgICAgbWVtY3B5KGFycmF5ICsgcGl2b3QgKiBzaXplLCBhcnJheSArIHN3YXBwb2ludCAqIHNpemUsIHNpemUpOwogICAgICAgIG1lbWNweShhcnJheSArIHN3YXBwb2ludCAqIHNpemUsIHRlbXAsIHNpemUpOwogICAgfQoKICAgIC8vIFJlY3Vyc2l2ZSBzb3J0aW5nIG9mIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0aXRpb25zCiAgICBxdWlja3NvcnRfaW50ZXJuYWwoYmFzZSwgc2l6ZSwgc3RhcnQsIHN3YXBwb2ludCwgY29tcGFyKTsgICAgICAgICAvLyBMZWZ0IHBhcnRpdGlvbgogICAgcXVpY2tzb3J0X2ludGVybmFsKGJhc2UsIHNpemUsIHN3YXBwb2ludCArIDEsIGVuZCwgY29tcGFyKTsgICAgICAvLyBSaWdodCBwYXJ0aXRpb24KfQoKCi8vIFRoaXMgaXMgdGhlIGV4YWN0IHNhbWUgZm9ybWF0IGFzIHFzb3J0LCBidXQgeW91Ci8vIG11c3QgTk9UIHVzZSBxc29ydCB0byBpbXBsZW1lbnQgdGhpcy4KLy8gWW91IHByb2JhYmx5IHdhbnQgdG8gY3JlYXRlIGEgcXVpY2tzb3J0X2ludGVybmFsIGZ1bmN0aW9uIHRoYXQKLy8geW91IGNhbGwgaW4gb3JkZXIgdG8gcHJvcGVybHkgaW1wbGVtZW50IHF1aWNrc29ydC4Kdm9pZCBxdWlja3NvcnRfYyh2b2lkICpiYXNlLCBzaXplX3Qgbm1lbWIsIHNpemVfdCBzaXplLCBpbnQgKCpjb21wYXIpKGNvbnN0IHZvaWQgKiwgY29uc3Qgdm9pZCAqKSkKewogICAgaWYgKCFiYXNlIHx8IHNpemUgPT0gMCB8fCBubWVtYiA8PSAxIHx8ICFjb21wYXIpIHsKICAgICAgICByZXR1cm47CiAgICB9CiAgICB1aW50OF90ICphcnJheSA9ICh1aW50OF90ICopYmFzZTsKCiAgICBib29sIGlzX3NvcnRlZCA9IHRydWU7ICAvLyBBc3N1bWUgdGhlIGFycmF5IGlzIHNvcnRlZCB1bmxlc3MgcHJvdmVuIG90aGVyd2lzZQogICAgLy8gQ2hlY2sgaWYgdGhlIGFycmF5IGlzIHByZS1zb3J0ZWQgb3IgYWxsLXNhbWUKICAgIGZvciAoc2l6ZV90IGkgPSAxOyBpIDwgbm1lbWI7IGkrKykgewogICAgICAgIGlmIChjb21wYXIoYXJyYXkgKyAoaSAtIDEpICogc2l6ZSwgYXJyYXkgKyBpICogc2l6ZSkgPiAwKSB7CiAgICAgICAgICAgIGlzX3NvcnRlZCA9IGZhbHNlOyAgLy8gRm91bmQgYW4gdW5zb3J0ZWQgcGFpcgogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgLy8gSWYgdGhlIGFycmF5IGlzIG5vdCBzb3J0ZWQsIHByb2NlZWQgd2l0aCBxdWlja3NvcnQKICAgIGlmICghaXNfc29ydGVkKSB7CiAgICAgICAgcXVpY2tzb3J0X2ludGVybmFsKGJhc2UsIHNpemUsIDAsIG5tZW1iLCBjb21wYXIpOwogICAgfSBlbHNlIHsKICAgICAgICBwcmludGYoIkFycmF5IGlzIGFscmVhZHkgc29ydGVkLiBTa2lwcGluZyBxdWlja3NvcnQuXG4iKTsKICAgIH0KfQoKaW50IG1haW4oKSB7CgogICAgLy8gU2VlZCBmb3IgcmFuZG9tbmVzcwogICAgc3JhbmQoKHVuc2lnbmVkKXRpbWUoTlVMTCkpOwoKCiAgICBpbnQgZGF0YVtdID0gezEwLCA5LCA4LCA3LCA2LCA1LCA0LCAzLCAyLCAxfTsgIC8vIFJldmVyc2Utc29ydGVkIGRhdGEKICAgIHNpemVfdCBubWVtYiA9IHNpemVvZihkYXRhKSAvIHNpemVvZihkYXRhWzBdKTsKICAgIHF1aWNrc29ydF9jKGRhdGEsIG5tZW1iLCBzaXplb2YoaW50KSwgaW50X2NvbXBhcik7CgogICAgLy8gUHJpbnQgc29ydGVkIGFycmF5CiAgICBwcmludGYoIlNvcnRlZCBhcnJheTpcbiIpOwogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBubWVtYjsgaSsrKSB7CiAgICAgICAgcHJpbnRmKCIlZCAiLCBkYXRhW2ldKTsKICAgIH0KICAgIHByaW50ZigiXG4iKTsKCiAgICBwcmludGYoIlxuUGF0aG9sb2dpY2FsIHByZS1zb3J0ZWQgdGVzdFxuIik7CiAgICBubWVtYj0xMDAwMDsKICAgIGludCBzb3J0ZWRfZGF0YVtubWVtYl07CiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IG5tZW1iOyBpKyspIHsKICAgICAgICBzb3J0ZWRfZGF0YVtpXSA9IGk7CiAgICB9CiAgICBjbG9ja190IHN0YXJ0X3RpbWUgPSBjbG9jaygpOwogICAgcXVpY2tzb3J0X2Moc29ydGVkX2RhdGEsIG5tZW1iLCBzaXplb2YoaW50KSwgaW50X2NvbXBhcik7CiAgICBjbG9ja190IHN0b3BfdGltZSA9IGNsb2NrKCk7CiAgICBkb3VibGUgdG90YWxfdGltZSA9IChkb3VibGUpKHN0b3BfdGltZSAtIHN0YXJ0X3RpbWUpIC8gQ0xPQ0tTX1BFUl9TRUMgKiAxZTY7IC8vIGluIG1pY3Jvc2Vjb25kcwogICAgcHJpbnRmKCJQYXRob2xvZ2ljYWwgcHJlLXNvcnRlZCB0aW1lOiAlLjJmIG1pY3Jvc2Vjb25kc1xuIiwgdG90YWxfdGltZSk7CgoKICAgIHByaW50ZigiXG5QYXRob2xvZ2ljYWwgYWxsLWVxdWFsIHRlc3RcbiIpOwogICAgaW50IGVxdWFsX2RhdGFbbm1lbWJdOwogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBubWVtYjsgaSsrKSB7CiAgICAgICAgZXF1YWxfZGF0YVtpXSA9IDQyOwogICAgfQogICAgc3RhcnRfdGltZSA9IGNsb2NrKCk7CiAgICBxdWlja3NvcnRfYyhlcXVhbF9kYXRhLCBubWVtYiwgc2l6ZW9mKGludCksIGludF9jb21wYXIpOwogICAgc3RvcF90aW1lID0gY2xvY2soKTsKICAgIHRvdGFsX3RpbWUgPSAoZG91YmxlKShzdG9wX3RpbWUgLSBzdGFydF90aW1lKSAvIENMT0NLU19QRVJfU0VDICogMWU2OyAvLyBpbiBtaWNyb3NlY29uZHMKICAgIHByaW50ZigiUGF0aG9sb2dpY2FsIGFsbC1lcXVhbCB0aW1lOiAlLjJmIG1pY3Jvc2Vjb25kc1xuIiwgdG90YWxfdGltZSk7CgoKICAgIHByaW50ZigiXG5SYW5kb21pemVkIHRlc3RcbiIpOwogICAgaW50IHJhbmRvbV9kYXRhW25tZW1iXTsKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgbm1lbWI7IGkrKykgewogICAgICAgIHJhbmRvbV9kYXRhW2ldID0gcmFuZCgpICUgMTAwMDsKICAgIH0KICAgIHN0YXJ0X3RpbWUgPSBjbG9jaygpOwogICAgcXVpY2tzb3J0X2MocmFuZG9tX2RhdGEsIG5tZW1iLCBzaXplb2YoaW50KSwgaW50X2NvbXBhcik7CiAgICBzdG9wX3RpbWUgPSBjbG9jaygpOwogICAgdG90YWxfdGltZSA9IChkb3VibGUpKHN0b3BfdGltZSAtIHN0YXJ0X3RpbWUpIC8gQ0xPQ0tTX1BFUl9TRUMgKiAxZTY7IC8vIGluIG1pY3Jvc2Vjb25kcwogICAgcHJpbnRmKCJSYW5kb21pemVkIHRpbWU6ICUuMmYgbWljcm9zZWNvbmRzXG4iLCB0b3RhbF90aW1lKTsKCgogICAgcmV0dXJuIDA7Cn0=