Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ahSort.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
117#ifndef AHSORT_H
118#define AHSORT_H
119
120#include <algorithm>
121#include <numeric>
122#include <ranges>
123#include <stdexcept>
124#include <utility>
125
126#include <ah-errors.H>
127#include <ahFunctional.H>
128#include <tpl_sort_utils.H>
129#include <tpl_dynDlist.H>
130#include <htlist.H>
131#include <ah-zip.H>
132
137#define List_Sort(List) \
138 \
145 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
146 List<T> sort(const List<T> & c, Cmp & cmp) \
147 { \
148 List<T> ret_val = c; \
149 mergesort<List, T, Cmp>(ret_val, cmp); \
150 return ret_val; \
151 } \
152 \
153 \
155 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
156 List<T> sort(const List<T> & c, Cmp && cmp = Cmp()) \
157 { \
158 return sort<T, Cmp>(c, cmp); \
159 } \
160 \
161\
168 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
169 List<T> sort(List<T> && c, Cmp & cmp) \
170 { \
171 mergesort<List, T, Cmp>(c, cmp); \
172 return std::move(c); \
173 } \
174 \
175 \
177 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
178 List<T> sort(List<T> && c, Cmp && cmp = Cmp()) \
179 { \
180 return sort<T, Cmp>(std::move(c), cmp); \
181 } \
182 \
183 \
190 template <typename T, class Cmp = Aleph::less<T>> inline \
191 List<T> & in_place_sort(List<T> & c, Cmp & cmp) \
192 { \
193 mergeinsertsort(c, cmp); \
194 return c; \
195 } \
196 \
197 \
199 template <typename T, class Cmp = Aleph::less<T>> inline \
200 List<T> & in_place_sort(List<T> & c, Cmp && cmp = Cmp()) \
201 { \
202 return in_place_sort<T, Cmp>(c, cmp); \
203 }
205
206namespace Aleph
207{
208 // Generate sort overloads for DynList and DynDlist
211
225 template<typename T, class Cmp = Aleph::less<T>>
226 [[nodiscard]] inline
228 {
231 return ret_val;
232 }
233
246 template<typename T, class Cmp = Aleph::less<T>>
247 [[nodiscard]] inline
249 {
250 introsort(a, cmp);
251 return std::move(a);
252 }
253
257 template<typename T, class Cmp = Aleph::less<T>>
258 [[nodiscard]] inline
259 Array<T> sort(const Array<T> & a, Cmp && cmp = Cmp())
260 {
261 Array<T> ret_val = a;
263 return ret_val;
264 }
265
269 template<typename T, class Cmp = Aleph::less<T>>
270 [[nodiscard]] inline
272 {
273 introsort(a, cmp);
274 return std::move(a);
275 }
276
297 template<typename Container,
298 class Cmp = std::less<typename Container::value_type>>
299 [[nodiscard]] inline
301 {
302 Container ret = c;
303 std::sort(ret.begin(), ret.end(), cmp);
304 return ret;
305 }
306
319 template<typename T, class Cmp = Aleph::less<T>>
320 inline
322 {
323 introsort(c, cmp);
324 return c;
325 }
326
330 template<typename T, class Cmp = Aleph::less<T>>
331 inline
333 {
334 introsort(c, cmp);
335 return c;
336 }
337
339
350 template<typename T, template <typename> class C>
351 class Compute_Ranks
352 {
353 using P = std::pair<T, size_t>;
354
355 public:
357 C<size_t> compute_ranks(const C<T> & c)
358 {
359 const size_t n = c.size();
361 indexes.reserve(n);
362 for (size_t i = 0; i < n; ++i)
363 indexes(i) = i; // DynArray auto-expands
364 quicksort_op(indexes, [&c](auto i1, auto i2)
365 {
366 return c(i1) < c(i2);
367 });
369 ret.reserve(n);
370 for (size_t i = 0; i < n; ++i)
371 ret(indexes(i)) = i; // DynArray auto-expands
372 return ret;
373 }
374
376 template<template <typename Type> class List>
378 {
379 C<T> items;
380 size_t n = 0;
382 c.for_each([&items, &n, &indexes](auto k)
383 {
384 items.append(k);
385 indexes.append(n++);
386 });
387 quicksort_op(indexes, [&items](auto i1, auto i2)
388 {
389 return items(i1) < items(i2);
390 });
392 ret.reserve(n);
393 for (size_t i = 0; i < n; ++i)
394 ret(indexes(i)) = i; // DynArray auto-expands
395 return ret;
396 }
397
399 C<P> compute_pair_ranks(const C<T> & c)
400 {
401 const size_t n = c.size();
403 indexes.reserve(n);
404 for (size_t i = 0; i < n; ++i)
405 indexes(i) = i;
406 quicksort_op(indexes, [&c](auto i1, auto i2)
407 {
408 return c(i1) < c(i2);
409 });
410 C<P> ret;
411 ret.reserve(n);
412 for (size_t i = 0; i < n; ++i)
413 {
414 auto idx = indexes(i);
415 ret(idx) = P(c(idx), i);
416 }
417 return ret;
418 }
419
421 template<template <typename Type> class List>
422 C<P> list_pair_ranks(const List<T> & c)
423 {
424 C<T> items;
425 size_t n = 0;
427 c.for_each([&items, &n, &indexes](auto k)
428 {
429 items.append(k);
430 indexes.append(n++);
431 });
432 quicksort_op(indexes, [&items](auto i1, auto i2)
433 {
434 return items(i1) < items(i2);
435 });
436 C<P> ret;
437 ret.reserve(n);
438 for (size_t i = 0; i < n; ++i)
439 {
440 auto idx = indexes(i);
441 ret(idx) = P(items(idx), i);
442 }
443 return ret;
444 }
445 };
446
453 template<typename T>
454 class Compute_Ranks<T, Array>
455 {
456 using P = std::pair<T, size_t>;
457
458 public:
461 {
462 const size_t n = c.size();
464 for (size_t i = 0; i < n; ++i)
465 indexes.append(i); // Use append to grow size
466 quicksort_op(indexes, [&c](auto i1, auto i2)
467 {
468 return c(i1) < c(i2);
469 });
471 ret.putn(n); // Allocate n slots (expands size)
472 for (size_t i = 0; i < n; ++i)
473 ret(indexes(i)) = i;
474 return ret;
475 }
476
479 {
480 const size_t n = c.size();
482 for (size_t i = 0; i < n; ++i)
483 indexes.append(i);
484 quicksort_op(indexes, [&c](auto i1, auto i2)
485 {
486 return c(i1) < c(i2);
487 });
488 Array<P> ret(n);
489 ret.putn(n); // Allocate n slots
490 for (size_t i = 0; i < n; ++i)
491 {
492 auto idx = indexes(i);
493 ret(idx) = P(c(idx), i);
494 }
495 return ret;
496 }
497 };
499
523 template<typename T>
525 {
526 return Compute_Ranks<T, Array>().compute_ranks(array);
527 }
528
532 template<typename T>
534 {
535 return Compute_Ranks<T, DynArray>().compute_ranks(array);
536 }
537
546 template<typename T>
548 {
549 return Compute_Ranks<T, DynArray>().list_compute_ranks(l);
550 }
551
560 template<typename T>
562 {
563 return Compute_Ranks<T, DynArray>().list_compute_ranks(l);
564 }
565
586 template<typename T>
587 [[nodiscard]] auto pair_ranks(const Array<T> & c)
588 {
589 return Compute_Ranks<T, Array>().compute_pair_ranks(c);
590 }
591
595 template<typename T>
596 [[nodiscard]] auto pair_ranks(const DynArray<T> & c)
597 {
598 return Compute_Ranks<T, DynArray>().compute_pair_ranks(c);
599 }
600
607 template<typename T>
609 {
611 return func.list_pair_ranks(l);
612 }
613
620 template<typename T>
622 {
624 return func.list_pair_ranks(l);
625 }
626
667 template<typename C, typename... Args,
668 typename Cmp = std::less<typename C::value_type>>
669 inline
670 void in_place_multisort_arrays(Cmp cmp, const bool stable, C & first, Args &... args)
671 {
672 const size_t n = first.size();
673 if (n == 0)
674 return;
675
676 const bool all_same_size = ((args.size() == n) && ...);
678 << "all arrays must have the same size";
679
680 std::vector<size_t> indices(n);
681 std::iota(indices.begin(), indices.end(), static_cast<size_t>(0));
682
683 const auto index_cmp_unstable = [&first, &cmp](const size_t i1, const size_t i2)
684 {
685 return cmp(first[i1], first[i2]);
686 };
687
688 const auto index_cmp_stable = [&first, &cmp](const size_t i1, const size_t i2)
689 {
690 if (cmp(first[i1], first[i2]))
691 return true;
692 if (cmp(first[i2], first[i1]))
693 return false;
694 return i1 < i2;
695 };
696
697 if (stable)
698 Aleph::mergesort(indices.data(), 0L,
699 static_cast<long>(indices.size() - 1), index_cmp_stable);
700 else
702
703 // Apply permutation.
704 // After sorting, indices[new_pos] = old_pos. Build inverse permutation
705 // perm[old_pos] = new_pos and fix it in-place via swaps.
707 for (size_t new_pos = 0; new_pos < n; ++new_pos)
709
710 using std::swap; // Enable ADL for user-defined swap
711 for (size_t i = 0; i < n; ++i)
712 while (perm[i] != i)
713 {
714 const size_t j = perm[i];
715 swap(first[i], first[j]);
716 (swap(args[i], args[j]), ...);
717 swap(perm[i], perm[j]);
718 }
719 }
720
721 template<typename C, typename... Args,
722 typename Cmp = std::less<typename C::value_type>>
723 inline
725 {
726 in_place_multisort_arrays(std::move(cmp), true, first, args...);
727 }
728
729
730} // end namespace Aleph
731
732#endif // AHSORT_H
Exception handling system with formatted messages for Aleph-w.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
Zip iterators and functional operations for multiple containers.
Functional programming utilities for Aleph-w containers.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
Node belonging to a double circular linked list with header node.
Definition tpl_dnode.H:106
Dynamic doubly linked list with O(1) size and bidirectional access.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
pair< size_t, string > P
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
T & swap(T &t1, T &t2)
Generic swap using object's swap method.
Definition ahTypes.H:121
auto pair_ranks(const Array< T > &c)
Computes (value, rank) pairs for each element in an Array.
Definition ahSort.H:587
void mergesort(T *a, const long l, const long r, std::vector< T > &buf, Compare cmp)
Sort an array using merge sort with a reusable buffer.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
DynArray< T > sort(const DynArray< T > &a, Cmp &&cmp=Cmp())
Returns a sorted copy of a DynArray.
Definition ahSort.H:227
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:321
DynList< std::pair< size_t, typename Container::Key_Type > > indexes(const Container &c)
Return pairs of (index, key).
Array< size_t > ranks(const Array< T > &array)
Computes the rank of each element in an Array.
Definition ahSort.H:524
Container stdsort(const Container &c, Cmp cmp=Cmp())
Sorts an STL-compatible container using std::sort.
Definition ahSort.H:300
void introsort(T *a, const long l, const long r, const Compare &cmp=Compare())
Sort an array using introsort (introspective sort).
void in_place_multisort_arrays(Cmp cmp, const bool stable, C &first, Args &... args)
Sorts multiple arrays in place, using the first array as the key.
Definition ahSort.H:670
List_Sort(DynList)
void quicksort_op(C< T > &a, const Compare &cmp=Compare(), const size_t threshold=Quicksort_Threshold)
Optimized quicksort for containers using operator().
static int * k
Dynamic doubly linked list implementation.
Comprehensive sorting algorithms and search utilities for Aleph-w.
DynList< int > l