std::partial_sort(3)
๐ NAME ๐
std::partial_sort โ ok so it's literally just std::partial_sort, that's the whole name bestie ๐ (yes this page is from the C++ Standard Libary manual, page std::partial_sort(3), and we're about to make it make sense ๐
)
๐ธ Synopsis ๐ธ
First things first: it's Defined in header <algorithm> ๐
There are four overloads, and they are all serving โญ
template< class RandomIt >
void partial_sort( RandomIt first, RandomIt middle, RandomIt last );
โจ overload (1), and it's constexpr since C++20 ๐ซถ
template< class ExecutionPolicy, class RandomIt >
void partial_sort( ExecutionPolicy&& policy,
RandomIt first, RandomIt middle, RandomIt last );
โจ overload (2), since C++17 ๐ซ
template< class RandomIt, class Compare >
void partial_sort( RandomIt first, RandomIt middle, RandomIt last,
Compare comp );
โจ overload (3), and it's constexpr since C++20 ๐ซถ
template< class ExecutionPolicy, class RandomIt, class Compare >
void partial_sort( ExecutionPolicy&& policy,
RandomIt first, RandomIt middle, RandomIt last,
Compare comp );
โจ overload (4), since C++17 ๐ซ
๐ฆ What it actually does ๐ฆ
So it rearranges elements such that the range [first, middle) contains the sorted middle - first smallest elements in the range [first, last). That's the whole vibe, no cap ๐ฅ
The order of equal elements is not guaranteed to be preserved ๐ and the order of the remaining elements in the range [middle, last) is unspecified โ so don't come for those, they're doing their own thing ๐
Now the detail drop, per overload ๐
- (1) โ elements are sorted with respect to
operator<(until C++20), and with respect tostd::less{}(since C++20) ๐ง - (3) โ elements are sorted with respect to
comp๐ฏ - (2),(4) โ same as (1),(3), but executed according to
policy. These overloads participate in overload resolution only ifstd::is_execution_policy_v<std::decay_t<ExecutionPolicy>>is true (until C++20), orstd::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>is true (since C++20) ๐
โ ๏ธ If any of the following conditions is satisfied, the behavior is undefined โ like, actual undefined behaviour, not the cute slang kind ๐ญ -[first, middle)or[middle, last)is not a valid range. - The type of*firstis not Swappable (until C++11). -RandomItis not ValueSwappable. - The type of*firstis not MoveConstructible (since C++11). - The type of*firstis not MoveAssignable.
๐ Parameters ๐
first,lastโ random access iterators defining the range ๐บ๏ธmiddleโ random access iterator defining the one-past-the-end iterator of the range to be sorted ๐ฏpolicyโ the execution policy to use. See execution policy for details. ๐ธcompโ comparison function object (i.e. an object that satisfies the requirements of Compare) which returnstrueif the first argument is less than (i.e. is ordered before) the second. ๐ง
The signature of the comparison function should be equivalent to the following:
bool cmp(const Type1& a, const Type2& b);
And the fine print on comp, because it matters fr fr ๐
โ while the signature does not need to have const&, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category (thus, Type1& is not allowed, nor is Type1 unless for Type1 a move is equivalent to a copy (since C++11)). The types Type1 and Type2 must be such that an object of type RandomIt can be dereferenced and then implicitly converted to both of them. ๐
๐ Type requirements ๐
RandomItmust meet the requirements of LegacyRandomAccessIterator ๐โโ๏ธComparemust meet the requirements of Compare โ๏ธ
๐ฅ Complexity ๐ฅ
Given M as middle - first, and N as last - first ๐งฎ
- (1),(2) โ approximately
Nยทlog(M)comparisons usingoperator<(until C++20),std::less{}(since C++20) โฑ๏ธ - (3),(4) โ approximately
Nยทlog(M)applications of the comparatorcompโฑ๏ธ
(and yes the original writes it as Mยทlog(M)... sorry, Nยทlog(M), with the cute little math script โ same numbers, promise ๐ซถ)
๐ Exceptions ๐
The overloads with a template parameter named ExecutionPolicy report errors as follows ๐
- If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicyis one of the standard policies,std::terminateis called. For any otherExecutionPolicy, the behavior is implementation-defined ๐ต - If the algorithm fails to allocate memory,
std::bad_allocis thrown ๐
๐ง Possible implementation ๐ง
See also the implementations in libstdc++ and libc++ ๐
partial_sort (1):
template<typename RandomIt>
constexpr //< since C++20
void partial_sort(RandomIt first, RandomIt middle, RandomIt last)
{
typedef typename std::iterator_traits<RandomIt>::value_type VT;
std::partial_sort(first, middle, last, std::less<VT>());
}
partial_sort (3):
namespace impl
{
template<typename RandomIt, typename Compare>
constexpr //< since C++20
void sift_down(RandomIt first, RandomIt last, const Compare& comp)
{
// sift down element at โfirstโ
const auto length = static_cast<std::size_t>(last - first);
std::size_t current = 0;
std::size_t next = 2;
while (next < length)
{
if (comp(*(first + next), *(first + (next - 1))))
--next;
if (!comp(*(first + current), *(first + next)))
return;
std::iter_swap(first + current, first + next);
current = next;
next = 2 * current + 2;
}
--next;
if (next < length && comp(*(first + current), *(first + next)))
std::iter_swap(first + current, first + next);
}
template<typename RandomIt, typename Compare>
constexpr //< since C++20
void heap_select(RandomIt first, RandomIt middle, RandomIt last, const Compare& comp)
{
std::make_heap(first, middle, comp);
for (auto i = middle; i != last; ++i)
{
if (comp(*i, *first))
{
std::iter_swap(first, i);
sift_down(first, middle, comp);
}
}
}
} // namespace impl
template<typename RandomIt, typename Compare>
constexpr //< since C++20
void partial_sort(RandomIt first, RandomIt middle, RandomIt last, Compare comp)
{
impl::heap_select(first, middle, last, comp);
std::sort_heap(first, middle, comp);
}
๐ Notes ๐
โ๏ธ Algorithm
The algorithm used is typically heap select to select the smallest elements, and heap sort to sort the selected elements in the heap in ascending order ๐
To select elements, a heap is used (see heap). For example, for operator< as comparison function, max-heap is used to select middle - first smallest elements ๐๏ธ
Heap sort is used after selection to sort [first, middle) selected elements (see std::sort_heap) ๐งบ
๐ Intended use
std::partial_sort algorithms are intended to be used for small constant numbers of [first, middle) selected elements ๐ (like, small. small small. don't be out here doing the most ๐
)
๐ Example ๐
Run this code, bestie ๐โโ๏ธ
#include <algorithm>
#include <array>
#include <functional>
#include <iostream>
void print(const auto& s, int middle)
{
for (int a : s)
std::cout << a << ' ';
std::cout << '\n';
if (middle > 0)
{
while (middle-- > 0)
std::cout << "--";
std::cout << '^';
}
else if (middle < 0)
{
for (auto i = s.size() + middle; --i; std::cout << " ")
{}
for (std::cout << '^'; middle++ < 0; std::cout << "--")
{}
}
std::cout << '\n';
};
int main()
{
std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
print(s, 0);
std::partial_sort(s.begin(), s.begin() + 3, s.end());
print(s, 3);
std::partial_sort(s.rbegin(), s.rbegin() + 4, s.rend());
print(s, -4);
std::partial_sort(s.rbegin(), s.rbegin() + 5, s.rend(), std::greater{});
print(s, -5);
}
๐ธ Possible output:
5 7 4 2 8 6 1 9 0 3
0 1 2 7 8 6 5 9 4 3
------^
4 5 6 7 8 9 3 2 1 0
^--------
4 3 2 1 0 5 6 7 8 9
^----------
๐ฆ Defect reports ๐ฆ
The following behavior-changing defect reports were applied retroactively to previously published C++ standards ๐
- P0896R4 โ applied to C++98. Behavior as published:
[first, middle)and[middle, last)were not required to be valid ranges. Correct behavior: the behavior is undefined if any of them is invalid ๐จ
๐ See also ๐
nth_elementโ partially sorts the given range making sure that it is partitioned by the given element (function template) ๐งฉpartial_sort_copyโ copies and partially sorts a range of elements (function template) ๐stable_sortโ sorts a range of elements while preserving order between equal elements (function template) ๐ซงsortโ sorts a range into ascending order (function template) ๐ผranges::partial_sort(C++20) โ sorts the first N elements of a range (niebloid) ๐
aaaaand that's the whole page, you ate it, I'm obsessed ๐ซถ๐ this little guide came straight from http://cppreference.com, dated 2024.06.10 โ go forth and partially sort, queen ๐โจ
๐ฆ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 ยท MIT
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms