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
123#ifndef AHSORT_H
124#define AHSORT_H
125
126#include <algorithm>
127#include <functional>
128#include <numeric>
129#include <stdexcept>
130#include <utility>
131#include <vector>
132
133#include <ah-errors.H>
134#include <ahFunctional.H>
135#include <tpl_sort_utils.H>
136#include <tpl_dynDlist.H>
137#include <htlist.H>
138#include <ah-zip.H>
139
144#define List_Sort(List) \
145 \
152 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
153 List<T> sort(const List<T> & c, Cmp & cmp) \
154 { \
155 List<T> ret_val = c; \
156 mergesort<List, T, Cmp>(ret_val, cmp); \
157 return ret_val; \
158 } \
159 \
160 \
162 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
163 List<T> sort(const List<T> & c, Cmp && cmp = Cmp()) \
164 { \
165 return sort<T, Cmp>(c, cmp); \
166 } \
167 \
168\
175 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
176 List<T> sort(List<T> && c, Cmp & cmp) \
177 { \
178 mergesort<List, T, Cmp>(c, cmp); \
179 return std::move(c); \
180 } \
181 \
182 \
184 template <typename T, class Cmp = Aleph::less<T>> [[nodiscard]] inline \
185 List<T> sort(List<T> && c, Cmp && cmp = Cmp()) \
186 { \
187 return sort<T, Cmp>(std::move(c), cmp); \
188 } \
189 \
190 \
197 template <typename T, class Cmp = Aleph::less<T>> inline \
198 List<T> & in_place_sort(List<T> & c, Cmp & cmp) \
199 { \
200 mergeinsertsort(c, cmp); \
201 return c; \
202 } \
203 \
204 \
206 template <typename T, class Cmp = Aleph::less<T>> inline \
207 List<T> & in_place_sort(List<T> & c, Cmp && cmp = Cmp()) \
208 { \
209 return in_place_sort<T, Cmp>(c, cmp); \
210 }
212
213namespace Aleph
214{
215 // Generate sort overloads for DynList and DynDlist
218
232 template<typename T, class Cmp = Aleph::less<T>>
233 [[nodiscard]] inline
235 {
238 return ret_val;
239 }
240
253 template<typename T, class Cmp = Aleph::less<T>>
254 [[nodiscard]] inline
256 {
257 introsort(a, cmp);
258 return std::move(a);
259 }
260
264 template<typename T, class Cmp = Aleph::less<T>>
265 [[nodiscard]] inline
266 Array<T> sort(const Array<T> & a, Cmp && cmp = Cmp())
267 {
268 Array<T> ret_val = a;
270 return ret_val;
271 }
272
276 template<typename T, class Cmp = Aleph::less<T>>
277 [[nodiscard]] inline
279 {
280 introsort(a, cmp);
281 return std::move(a);
282 }
283
304 template<typename Container,
305 class Cmp = std::less<typename Container::value_type>>
306 [[nodiscard]] inline
308 {
309 Container ret = c;
310 std::sort(ret.begin(), ret.end(), cmp);
311 return ret;
312 }
313
326 template<typename T, class Cmp = Aleph::less<T>>
327 inline
329 {
330 introsort(c, cmp);
331 return c;
332 }
333
337 template<typename T, class Cmp = Aleph::less<T>>
338 inline
340 {
341 introsort(c, cmp);
342 return c;
343 }
344
383 template <class C,
385 [[nodiscard]] inline Array<size_t> argsort(const C &a,
386 const Compare &cmp = Compare())
387 {
388 return build_index(a, cmp);
389 }
390
431 template <class C,
434 const Compare &cmp = Compare())
435 {
436 return stable_build_index(a, cmp);
437 }
438
440
451 template<typename T, template <typename> class C>
452 class Compute_Ranks
453 {
454 using P = std::pair<T, size_t>;
455
456 public:
469 C<size_t> compute_ranks(const C<T> & c)
470 {
471 const size_t n = c.size();
473 indexes.reserve(n);
474 for (size_t i = 0; i < n; ++i)
475 indexes(i) = i; // DynArray auto-expands
476 quicksort_op(indexes, [&c](auto i1, auto i2)
477 {
478 return c(i1) < c(i2);
479 });
481 ret.reserve(n);
482 for (size_t i = 0; i < n; ++i)
483 ret(indexes(i)) = i; // DynArray auto-expands
484 return ret;
485 }
486
501 template<template <typename Type> class List>
503 {
504 C<T> items;
505 size_t n = 0;
507 c.for_each([&items, &n, &indexes](auto k)
508 {
509 items.append(k);
510 indexes.append(n++);
511 });
512 quicksort_op(indexes, [&items](auto i1, auto i2)
513 {
514 return items(i1) < items(i2);
515 });
517 ret.reserve(n);
518 for (size_t i = 0; i < n; ++i)
519 ret(indexes(i)) = i; // DynArray auto-expands
520 return ret;
521 }
522
536 C<P> compute_pair_ranks(const C<T> & c)
537 {
538 const size_t n = c.size();
540 indexes.reserve(n);
541 for (size_t i = 0; i < n; ++i)
542 indexes(i) = i;
543 quicksort_op(indexes, [&c](auto i1, auto i2)
544 {
545 return c(i1) < c(i2);
546 });
547 C<P> ret;
548 ret.reserve(n);
549 for (size_t i = 0; i < n; ++i)
550 {
551 auto idx = indexes(i);
552 ret(idx) = P(c(idx), i);
553 }
554 return ret;
555 }
556
571 template<template <typename Type> class List>
572 C<P> list_pair_ranks(const List<T> & c)
573 {
574 C<T> items;
575 size_t n = 0;
577 c.for_each([&items, &n, &indexes](auto k)
578 {
579 items.append(k);
580 indexes.append(n++);
581 });
582 quicksort_op(indexes, [&items](auto i1, auto i2)
583 {
584 return items(i1) < items(i2);
585 });
586 C<P> ret;
587 ret.reserve(n);
588 for (size_t i = 0; i < n; ++i)
589 {
590 auto idx = indexes(i);
591 ret(idx) = P(items(idx), i);
592 }
593 return ret;
594 }
595 };
596
603 template<typename T>
604 class Compute_Ranks<T, Array>
605 {
606 using P = std::pair<T, size_t>;
607
608 public:
623 {
624 const size_t n = c.size();
626 for (size_t i = 0; i < n; ++i)
627 indexes.append(i); // Use append to grow size
628 quicksort_op(indexes, [&c](auto i1, auto i2)
629 {
630 return c(i1) < c(i2);
631 });
633 ret.putn(n); // Allocate n slots (expands size)
634 for (size_t i = 0; i < n; ++i)
635 ret(indexes(i)) = i;
636 return ret;
637 }
638
653 {
654 const size_t n = c.size();
656 for (size_t i = 0; i < n; ++i)
657 indexes.append(i);
658 quicksort_op(indexes, [&c](auto i1, auto i2)
659 {
660 return c(i1) < c(i2);
661 });
662 Array<P> ret(n);
663 ret.putn(n); // Allocate n slots
664 for (size_t i = 0; i < n; ++i)
665 {
666 auto idx = indexes(i);
667 ret(idx) = P(c(idx), i);
668 }
669 return ret;
670 }
671 };
673
697 template<typename T>
699 {
700 return Compute_Ranks<T, Array>().compute_ranks(array);
701 }
702
706 template<typename T>
708 {
709 return Compute_Ranks<T, DynArray>().compute_ranks(array);
710 }
711
720 template<typename T>
722 {
723 return Compute_Ranks<T, DynArray>().list_compute_ranks(l);
724 }
725
734 template<typename T>
736 {
737 return Compute_Ranks<T, DynArray>().list_compute_ranks(l);
738 }
739
760 template<typename T>
761 [[nodiscard]] auto pair_ranks(const Array<T> & c)
762 {
763 return Compute_Ranks<T, Array>().compute_pair_ranks(c);
764 }
765
769 template<typename T>
770 [[nodiscard]] auto pair_ranks(const DynArray<T> & c)
771 {
772 return Compute_Ranks<T, DynArray>().compute_pair_ranks(c);
773 }
774
781 template<typename T>
783 {
785 return func.list_pair_ranks(l);
786 }
787
794 template<typename T>
796 {
798 return func.list_pair_ranks(l);
799 }
800
841 template<typename C, typename... Args,
842 typename Cmp = std::less<typename C::value_type>>
843 inline
844 void in_place_multisort_arrays(Cmp cmp, const bool stable, C & first, Args &... args)
845 {
846 const size_t n = first.size();
847 if (n == 0)
848 return;
849
850 const bool all_same_size = ((args.size() == n) && ...);
852 << "all arrays must have the same size";
853
854 std::vector<size_t> indices(n);
855 std::iota(indices.begin(), indices.end(), static_cast<size_t>(0));
856
857 const auto index_cmp_unstable = [&first, &cmp](const size_t i1, const size_t i2)
858 {
859 return cmp(first[i1], first[i2]);
860 };
861
862 const auto index_cmp_stable = [&first, &cmp](const size_t i1, const size_t i2)
863 {
864 if (cmp(first[i1], first[i2]))
865 return true;
866 if (cmp(first[i2], first[i1]))
867 return false;
868 return i1 < i2;
869 };
870
871 if (stable)
872 Aleph::mergesort(indices.data(), 0L,
873 static_cast<long>(indices.size() - 1), index_cmp_stable);
874 else
876
877 // Apply permutation.
878 // After sorting, indices[new_pos] = old_pos. Build inverse permutation
879 // perm[old_pos] = new_pos and fix it in-place via swaps.
881 for (size_t new_pos = 0; new_pos < n; ++new_pos)
883
884 using std::swap; // Enable ADL for user-defined swap
885 for (size_t i = 0; i < n; ++i)
886 while (perm[i] != i)
887 {
888 const size_t j = perm[i];
889 swap(first[i], first[j]);
890 (swap(args[i], args[j]), ...);
891 swap(perm[i], perm[j]);
892 }
893 }
894
895 template<typename C, typename... Args,
896 typename Cmp = std::less<typename C::value_type>>
897 inline
899 {
900 in_place_multisort_arrays(std::move(cmp), true, first, args...);
901 }
902
903
904} // end namespace Aleph
905
906#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:644
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:138
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:196
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
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.
Doubly-linked list (defined in tpl_dynList.H).
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:4129
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Array< size_t > stable_build_index(const C &a, const Compare &cmp=Compare())
Build a stable index array for indirect sorting.
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:761
Array< size_t > stable_argsort(const C &a, const Compare &cmp=Compare())
Return stable sorted-order indices for an array-like container.
Definition ahSort.H:433
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:234
Array< size_t > build_index(const C &a, const Compare &cmp=Compare())
Build an index array for indirect sorting.
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:328
DynList< std::pair< size_t, typename Container::Key_Type > > indexes(const Container &c)
Return pairs of (index, key).
void mergesort(T *a, const long l, const long r, Array< T > &buf, Compare cmp)
Sort an array using merge sort with a reusable buffer.
Array< size_t > ranks(const Array< T > &array)
Computes the rank of each element in an Array.
Definition ahSort.H:698
Array< size_t > argsort(const C &a, const Compare &cmp=Compare())
Return indices that visit an array-like container in sorted order.
Definition ahSort.H:385
Container stdsort(const Container &c, Cmp cmp=Cmp())
Sorts an STL-compatible container using std::sort.
Definition ahSort.H:307
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:844
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