std::partial_sort
Определён в заголовочном файле <algorithm> | ||
|---|---|---|
template< class RandomIt > void partial_sort( RandomIt first, RandomIt middle, RandomIt last ); | (1) | (начиная с C++20, constexpr) |
template< class ExecutionPolicy, class RandomIt >
void partial_sort( ExecutionPolicy&& policy,
RandomIt first, RandomIt middle, RandomIt last );
| (2) | (начиная с C++17) |
template< class RandomIt, class Compare >
void partial_sort( RandomIt first, RandomIt middle, RandomIt last,
Compare comp );
| (3) | (начиная с C++20, constexpr) |
template< class ExecutionPolicy, class RandomIt, class Compare >
void partial_sort( ExecutionPolicy&& policy,
RandomIt first, RandomIt middle, RandomIt last,
Compare comp );
| (4) | (начиная с C++17) |
Переставляет элементы так, чтобы диапазон [first, middle) содержал отсортированные middle − first наименьших элементов диапазона [first, last).
Сохранение порядка равных элементов не гарантируется. Порядок остальных элементов диапазона [middle, last) не определён.
comp.policy.true: |
| (до C++20) |
|
| (начиная с C++20) |
Если выполняется любое из следующих условий, поведение не определено:
-
[first,middle)или[middle,last)не является допустимым диапазоном.
| (до C++11) |
| (начиная с C++11) |
Параметры
| first, last | - | пара итераторов, задающая диапазон переставляемых элементов |
| middle | - | диапазон [first, middle) будет содержать отсортированные элементы |
| policy | - | политика выполнения, используемая алгоритмом |
| comp | - | объект-функция сравнения (то есть объект, удовлетворяющий требованиям Compare), который возвращает true, если первый аргумент меньше второго (то есть упорядочен перед ним). Сигнатура функции сравнения должна быть эквивалентна следующей: boolcmp(constType1&a,constType2&b); Хотя сигнатура не обязана содержать const&, функция не должна изменять переданные ей объекты и должна принимать все значения типа (возможно, const) |
| Требования к типам | ||
-RandomIt должен удовлетворять требованиям LegacyRandomAccessIterator. |
||
-Compare должен удовлетворять требованиям Compare. |
||
Сложность
Пусть \(\scriptsize M\)M — это middle - first, а \(\scriptsize N\)N — это last - first:
std::less{}(начиная с C++20).comp.Исключения
Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, приводит к выбросу исключения и
ExecutionPolicyявляется одной из стандартных политик, вызываетсяstd::terminate. Для любого другого значенияExecutionPolicyповедение определяется реализацией. - Если алгоритму не удаётся выделить память, выбрасывается
std::bad_alloc.
Возможная реализация
См. также реализации в libstdc++ и 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);
}
|
Примечания
Алгоритм
Обычно алгоритм использует выбор с помощью кучи для выбора наименьших элементов и сортировку кучей для сортировки выбранных элементов в куче по возрастанию.
Для выбора элементов используется куча (см. куча). Например, для функции сравнения operator< используется max-heap для выбора middle − first наименьших элементов.
После выбора используется сортировка кучей, чтобы отсортировать [first, middle) выбранных элементов (см. std::sort_heap).
Предполагаемое использование
Алгоритмы std::partial_sort предназначены для работы с небольшим фиксированным количеством [first, middle) выбранных элементов.
Пример
#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);
}
Возможный вывод:
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
^----------
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| P0896R4 | C++98 |
[first, middle) и [middle, last)не требовалось быть допустимыми диапазонами | поведение не определено, если любой из них недопустим |
См. также
| находит N-й элемент так, как если бы диапазон был отсортирован (шаблон функции и объект-функция алгоритма) |
|
|
(C++20) | |
| копирует и частично сортирует диапазон элементов (шаблон функции и объект-функция алгоритма) |
|
|
(C++20) | |
| сортирует диапазон элементов, сохраняя относительный порядок эквивалентных элементов (шаблон функции и объект-функция алгоритма) |
|
|
(C++20) | |
| сортирует диапазон элементов (шаблон функции и объект-функция алгоритма) |
|
|
(C++20) | |
|
(C++20) | сортирует первые N элементов диапазона (объект-функция алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/partial_sort