[/ File indirect_sort.qbk] [section:indirect_sort indirect_sort ] [/license Copyright (c) 2023 Marshall Clow Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] There are times that you want a sorted version of a sequence, but for some reason or another, you don't really want to sort them. Maybe the elements in the sequence are non-copyable (or non-movable), or the sequence is const, or they're just really expensive to move around. An example of this might be a sequence of records from a database. Nevertheless, you might want to sort them. That's where indirect sorting comes in. In a "normal" sort, the elements of the sequence to be sorted are shuffled in place. In indirect sorting, the elements are unchanged, but the sort algorithm returns to you a "permutation" of the elements that, when applied, will leave the elements in the sequence in a sorted order. Say you have a sequence `[first, last)` of 1000 items that are expensive to swap: ``` std::sort(first, last); // ['O(N ln N)] comparisons and ['O(N ln N)] swaps (of the element type). ``` On the other hand, using indirect sorting: ``` auto permutation = boost::algorithm::indirect_sort(first, last); // ['O(N lg N)] comparisons and ['O(N lg N)] swaps (of size_t). boost::algorithm::apply_permutation(first, last, perm.begin(), perm.end()); // ['O(N)] swaps (of the element type) ``` If the element type is sufficiently expensive to swap, then 10,000 swaps of size_t + 1000 swaps of the element_type could be cheaper than 10,000 swaps of the element_type. Or maybe you don't need the elements to actually be sorted - you just want to traverse them in a sorted order: ``` auto permutation = boost::algorithm::indirect_sort(first, last); for (size_t idx: permutation) std::cout << first[idx] << std::endl; ``` More to come here .... [heading interface] The function `indirect_sort` a `vector` containing the permutation necessary to put the input sequence into a sorted order. One version uses `std::less` to do the comparisons; the other lets the caller pass predicate to do the comparisons. ``` template std::vector indirect_sort (RAIterator first, RAIterator last); template std::vector indirect_sort (RAIterator first, RAIterator last, BinaryPredicate pred); ``` [heading Examples] [heading Iterator Requirements] `indirect_sort` requires random-access iterators. [heading Complexity] Both of the variants of `indirect_sort` run in ['O(N lg N)] time; they are not more (or less) efficient than `std::sort`. There is an extra layer of indirection on each comparison, but all off the swaps are done on values of type `size_t` [heading Exception Safety] [heading Notes] [endsect] [/ File indirect_sort.qbk Copyright 2023 Marshall Clow Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ]