std::rotate
Определено в заголовочном файле <algorithm> | ||
|---|---|---|
template< class ForwardIt > ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last ); | (1) | (constexpr с C++20) |
template< class ExecutionPolicy, class ForwardIt >
ForwardIt rotate( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt middle, ForwardIt last );
| (2) | (с C++17) |
std::rotate меняет местами элементы в диапазоне [first, last) таким образом, что элементы из [first, middle) перемещаются после элементов из [middle, last), сохраняя порядок элементов в обоих диапазонах.policy.true: |
| (до C++20) |
|
| (начиная с C++20) |
Если выполняется любое из следующих условий, поведение программы не определено:
-
[first,middle)или[middle,last)не является допустимым диапазоном.
| (до C++11) |
| (начиная с C++11) |
Параметры
| first, last | - | пара итераторов, задающая диапазон элементов для циклического сдвига |
| middle | - | элемент, который должен оказаться в начале диапазона после циклического сдвига |
| policy | - | используемая политика выполнения |
| Требования к типам | ||
-ForwardIt должен соответствовать требованиям LegacyForwardIterator. |
||
Возвращаемое значение
Итератор элемента, на который изначально указывал *first, то есть std::distance(middle, last)-й следующий итератор после first.
Сложность
Не более std::distance(first, last) обменов.
Исключения
Перегрузка с параметром шаблона с именем ExecutionPolicy сообщает об ошибках следующим образом:
- Если выполнение функции, вызванной в рамках алгоритма, приводит к выбросу исключения, а
ExecutionPolicyявляется одной из стандартных политик, вызываетсяstd::terminate. Для любого другого значенияExecutionPolicyповедение определяется реализацией. - Если алгоритму не удаётся выделить память, выбрасывается
std::bad_alloc.
Возможная реализация
См. также реализации в libstdc++, libc++ и MSVC STL.
template<class ForwardIt>
constexpr // since C++20
ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last)
{
if (first == middle)
return last;
if (middle == last)
return first;
ForwardIt write = first;
ForwardIt next_read = first; // read position for when “read” hits “last”
for (ForwardIt read = middle; read != last; ++write, ++read)
{
if (write == next_read)
next_read = read; // track where “first” went
std::iter_swap(write, read);
}
// rotate the remaining sequence into place
rotate(write, next_read, last);
return write;
}
|
Примечания
std::rotate в распространённых реализациях работает эффективнее, если ForwardIt соответствует требованиям LegacyBidirectionalIterator или (что ещё лучше) LegacyRandomAccessIterator.
Реализации (например, MSVC STL) могут включать векторизацию, если тип итератора соответствует требованиям LegacyContiguousIterator, а обмен значениями его типа не вызывает ни одной нетривиальной функции-члена, специальной для этого типа, и ни одной функции swap, найденной с помощью ADL.
Пример
std::rotate — распространённый строительный блок многих алгоритмов. В этом примере демонстрируется сортировка вставками.
#include <algorithm>
#include <iostream>
#include <vector>
auto print = [](const auto remark, const auto& v)
{
std::cout << remark;
for (auto n : v)
std::cout << n << ' ';
std::cout << '\n';
};
int main()
{
std::vector<int> v{2, 4, 2, 0, 5, 10, 7, 3, 7, 1};
print("before sort:\t\t", v);
// insertion sort
for (auto i = v.begin(); i != v.end(); ++i)
std::rotate(std::upper_bound(v.begin(), i, *i), i, i + 1);
print("after sort:\t\t", v);
// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
print("simple rotate left:\t", v);
// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
print("simple rotate right:\t", v);
}
Вывод:
before sort: 2 4 2 0 5 10 7 3 7 1 after sort: 0 1 2 2 3 4 5 7 7 10 simple rotate left: 1 2 2 3 4 5 7 7 10 0 simple rotate right: 0 1 2 2 3 4 5 7 7 10
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| LWG 488 | C++98 | новая позиция элемента, на который указывает first, не возвращалась | возвращается |
См. также
| копирует и циклически сдвигает диапазон элементов (шаблон функции и функциональный объект алгоритма) |
|
|
(C++20) | |
|
(C++20) | циклически сдвигает порядок элементов в диапазоне (функциональный объект алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/rotate