2023-12-05 09:49:07 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <span>
|
|
|
|
#include <thread>
|
|
|
|
#include <mutex>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class QuickSorterMT {
|
|
|
|
public:
|
|
|
|
template<typename C>
|
|
|
|
QuickSorterMT(C cmp, int max_depth) : cmp(cmp), max_depth(max_depth) {
|
|
|
|
static_assert(std::is_same<std::invoke_result_t<C, T, T>, bool>(), "C must be a function that returns a bool");
|
|
|
|
}
|
|
|
|
|
|
|
|
auto sort(std::vector<T> &data) -> void {
|
|
|
|
std::span<T> sortable(data);
|
|
|
|
qsort(sortable, 0, max_depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
auto parition(std::span<T> &data) -> std::pair<std::span<T>, std::span<T>> {
|
2023-12-05 09:57:17 +00:00
|
|
|
auto pivot = data.begin();
|
|
|
|
std::advance(pivot, std::distance(data.begin(), data.end()) / 2);
|
2023-12-05 09:49:07 +00:00
|
|
|
|
2023-12-05 09:57:17 +00:00
|
|
|
auto lefti = data.begin();
|
2023-12-05 19:18:23 +00:00
|
|
|
auto righti = data.end() - 1;
|
2023-12-05 09:49:07 +00:00
|
|
|
|
|
|
|
while (1) {
|
2023-12-05 19:18:23 +00:00
|
|
|
for (; cmp((*lefti), (*pivot)); lefti++);
|
|
|
|
for (; !cmp((*righti), (*pivot)); righti--);
|
2023-12-05 09:49:07 +00:00
|
|
|
|
|
|
|
if (lefti >= righti) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-12-05 19:18:23 +00:00
|
|
|
std::swap(*lefti, *righti);
|
2023-12-05 09:49:07 +00:00
|
|
|
}
|
|
|
|
|
2023-12-05 19:18:23 +00:00
|
|
|
return {std::span<T>(data.begin(), pivot - 1), std::span<T>(pivot + 1, data.end())};
|
2023-12-05 09:49:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto qsort(std::span<T> &data, int depth, const int &mdepth) -> void {
|
|
|
|
if (std::distance(data.begin(), data.end()) <= 1) {
|
|
|
|
return;
|
|
|
|
} else if (std::distance(data.begin(), data.end()) == 2) {
|
|
|
|
if (cmp(data[1], data[0])) {
|
|
|
|
std::swap(data[0], data[1]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-05 09:57:17 +00:00
|
|
|
auto res = parition(data);
|
2023-12-05 19:18:23 +00:00
|
|
|
auto &left = res.first;
|
|
|
|
auto &right = res.second;
|
2023-12-05 09:49:07 +00:00
|
|
|
|
|
|
|
if (depth < mdepth) {
|
|
|
|
std::thread left_thread([&]() { qsort(left, depth + 1, mdepth); });
|
|
|
|
std::thread right_thread([&]() { qsort(right, depth + 1, mdepth); });
|
|
|
|
|
|
|
|
left_thread.join();
|
|
|
|
right_thread.join();
|
|
|
|
} else {
|
|
|
|
qsort(left, depth + 1, mdepth);
|
|
|
|
qsort(right, depth + 1, mdepth);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::function<bool(T, T)> cmp;
|
|
|
|
const int max_depth;
|
|
|
|
};
|