std::rotate
Определено в заголовке <algorithm> | ||
|---|---|---|
| (1) | ||
template< class ForwardIt > ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last ); | (до C++20) | |
template< class ForwardIt >
constexpr ForwardIt rotate( ForwardIt first,
ForwardIt middle, ForwardIt last );
| (с 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. Этот перегруз не участвует в разрешении перегрузки, если |
| (до C++20) |
|
| (с C++20) |
Если [first, middle) или [middle, last) не является валидным диапазоном, поведение не определено.
Параметры
| first | - | начало исходного диапазона |
| middle | - | элемент, который должен появиться в начале сдвинутого диапазона |
| last | - | конец исходного диапазона |
| policy | - | используемая политика выполнения. Подробнее см. политика выполнения. |
| Требования к типу | ||
-ForwardIt должны удовлетворять требованиям ValueSwappable и LegacyForwardIterator. |
||
-Тип разыменованного ForwardIt должен удовлетворять требованиям MoveAssignable и MoveConstructible. |
||
Возвращаемое значение
Итератор, равный:
-
last, еслиfirst == middleравноtrue, -
first, еслиmiddle == lastравноtrue, -
first + (last - middle)[1] в противном случае, т.е. новое расположение элемента, на который указываетfirst.
- Операции
+и-не обязаны поддерживаться, они используются только для представления позиции возвращаемого итератора.
Сложность
Линейная по расстоянию между first и last.
Исключения
Перегрузка с параметром шаблона ExecutionPolicy сообщает об ошибках следующим образом:
- Если во время выполнения функции, вызванной как часть алгоритма, возникает исключение, а
ExecutionPolicy— одна из стандартных политик, вызываетсяstd::terminate. Для любой другойExecutionPolicy, поведение определяется реализацией. - Если алгоритм не может выделить память, выбрасывается
std::bad_alloc.
Примечания
std::rotate имеет лучшую эффективность на распространённых реализациях, если ForwardIt удовлетворяет LegacyBidirectionalIterator или (лучше) LegacyRandomAccessIterator.
Реализации (например, MSVC STL) могут включить векторизацию, когда тип итератора удовлетворяет LegacyContiguousIterator, а обмен его типом значения не вызывает ни нетривиальных специальных функций-членов, ни ADL-найденных swap.
Возможная реализация
См. также реализации в 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 является распространённым строительным блоком во многих алгоритмах. Этот пример демонстрирует сортировку вставкой.
#include <algorithm>
#include <iostream>
#include <vector>
auto print = [](auto const remark, auto const& 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++.
| DR | Применено к | Поведение, как опубликовано | Корректное поведение |
|---|---|---|---|
| LWG 488 | C++98 | новая позиция элемента, на который указывает first не возвращалась | возвращалась |
См. также
| копирует и циклически сдвигает диапазон элементов (шаблон функции) |
|
|
(C++20) | циклически сдвигает элементы в диапазоне (niebloid) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/rotate