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
227 DynArray<T> sort(const DynArray<T> & a, Cmp && cmp = Cmp())
228 {
231 return ret_val;
232 }
233
246 template<typename T, class Cmp = Aleph::less<T>>
247 [[nodiscard]] inline
248 DynArray<T> sort(DynArray<T> && a, Cmp && cmp = Cmp())
249 {
250 quicksort_op(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
271 Array<T> sort(Array<T> && a, Cmp && cmp = Cmp())
272 {
273 quicksort_op(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
300 Container stdsort(const Container & c, Cmp cmp = Cmp())
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 quicksort_op(c, cmp);
324 return c;
325 }
326
330 template<typename T, class Cmp = Aleph::less<T>>
331 inline
332 Array<T> & in_place_sort(Array<T> & c, Cmp cmp = Cmp())
333 {
334 quicksort_op(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
665 template<typename C, typename... Args,
666 typename Cmp = std::less<typename C::value_type>>
667 inline
668 void in_place_multisort_arrays(Cmp cmp, C & first, Args &... args)
669 {
670 const size_t n = first.size();
671 if (n == 0)
672 return;
673
674 const bool all_same_size = ((args.size() == n) && ...);
676 << "all arrays must have the same size";
677
678 std::vector<size_t> indices(n);
679 std::iota(indices.begin(), indices.end(), static_cast<size_t>(0));
680
681 std::stable_sort(indices.begin(), indices.end(), [&first, &cmp](size_t i1, size_t i2)
682 {
683 return cmp(first[i1], first[i2]);
684 });
685
686 // Apply permutation using cycle-chasing algorithm
687 // Mark visited positions by setting indices[i] = i after processing
688 using std::swap; // Enable ADL for user-defined swap
689 for (size_t i = 0; i < n; ++i)
690 {
691 // Skip if this position is already in its final place
692 // or if we've already processed this cycle
693 if (indices[i] == i)
694 continue;
695
696 // Follow the cycle starting at position i
697 size_t current = i;
698 while (indices[current] != i)
699 {
700 size_t next = indices[current];
701 swap(first[current], first[next]);
702 (swap(args[current], args[next]), ...);
703 indices[current] = current; // Mark as processed
704 current = next;
705 }
706 indices[current] = current; // Mark the last element of the cycle
707 }
708 }
709
710
711} // end namespace Aleph
712
713#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:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:333
Dynamic doubly linked list with O(1) size and bidirectional access.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:685
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
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 in_place_multisort_arrays(Cmp cmp, C &first, Args &... args)
Sorts multiple arrays in place, using the first array as the key.
Definition ahSort.H:668
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
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 next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:175
List_Sort(DynList)
DynList< T > maps(const C &c, Op op)
Classic map operation.
void quicksort_op(C< T > &a, const Compare &cmp=Compare(), const size_t threshold=Quicksort_Threshold)
Optimized quicksort for containers using operator().
Dynamic doubly linked list implementation.
Comprehensive sorting algorithms and search utilities for Aleph-w.
DynList< int > l