Namespaces
Variants

std::ranges::rotate

ja.cppreference.net から
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとレンジ上のアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy、 ranges::sort、...
ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割された範囲に対して)
集合操作 (ソート済み範囲に対して)
マージ操作 (ソート済み範囲に対して)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
置換操作


 
制約付きアルゴリズム
このメニューのすべての名前は名前空間 std::ranges
非変更シーケンス操作
変更シーケンス操作
分割操作
ソート操作
二分探索操作 (ソート済み範囲に対して)
       
       
集合操作 (ソート済み範囲に対して)
ヒープ操作
最小/最大操作
       
       
置換操作
畳み込み操作
数値操作
(C++23)            
未初期化ストレージに対する操作
戻り値の型
 
ヘッダで定義 <algorithm>
呼び出しシグネチャ
template< std::permutable I, std::sentinel_for<I> S >
constexpr ranges::subrange<I>
    rotate( I first, I middle, S last );
(1) (C++20から)
template< ranges::forward_range R >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>
    rotate( R&& r, ranges::iterator_t<R> middle );
(2) (C++20から)
1) 左ローテーションを行います 要素の範囲に対して。具体的には、ranges::rotate 範囲内の要素を交換し、[first, last) そのようにして要素 *middle が新しい範囲の最初の要素になり、*(middle - 1) が最後の要素になります。
動作は未定義です。もし [first, last) が有効な範囲でないか、middle が [first, last) に含まれていない場合。
2) 次と同じ:(1) ですが、範囲として r を範囲として使用し、ranges::begin(r) として first と ranges::end(r) として lastこのページで説明されている関数のようなエンティティは、

アルゴリズム関数オブジェクト (非公式に niebloids として知られています)。すなわち: 明示的なテンプレート引数リストは、それらのいずれかを呼び出すときに指定できません。

パラメータ

first, last - 回転させる要素の 範囲 を定義するイテレータ-番兵ペア
r - 回転させる要素の範囲
middle - 回転後の範囲の先頭に現れるべき要素を指すイテレータ

戻り値

{ new_first, last } 、ここで new_first は ranges:: next ( first, ranges:: distance ( middle, last ) ) と等価であり、 first が指していた要素の新しい位置を示します。

計算量

Linear at worst: ranges:: distance ( first, last ) 回のスワップ。

注記

ranges::rotate は、 I が bidirectional_iterator または(さらに良い) random_access_iterator をモデル化する場合、一般的な実装ではより高い効率性を持ちます。

実装(例: MSVC STL )は、イテレータ型が contiguous_iterator をモデルし、その値型の交換が非自明な特殊メンバ関数も ADL で発見された swap も呼び出さない場合、ベクトル化を有効化することがあります。

実装例

実装については libstdc++ および MSVC STL も参照してください。

struct rotate_fn
{
    template<std::permutable I, std::sentinel_for<I> S>
    constexpr ranges::subrange<I>
        operator()(I first, I middle, S last) const
    {
        if (first == middle)
        {
            auto last_it = ranges::next(first, last);
            return {last_it, last_it};
        }
        if (middle == last)
            return {std::move(first), std::move(middle)};
        if constexpr (std::bidirectional_iterator<I>)
        {
            ranges::reverse

(注:指定された条件により、HTMLタグ・属性は保持され、タグ内のテキスト(例示されていませんが)やC++固有用語は翻訳対象外のため、変更はありません)(first, middle);
            auto last_it = ranges::next(first, last);
            ranges::reverse(middle, last_it);
            if constexpr (std::random_access_iterator<I>)
            {
                ranges::reverse(first, last_it);
                return {first + (last_it - middle), std::move(last_it)};
            }
            else
            {
                auto mid_last = last_it;
                do
                {
                    ranges::iter_swap(first, --mid_last);
                    ++first;
                }
                while (first != middle && mid_last != middle);
                ranges::reverse(first, mid_last);
                if (first == middle)
                    return {std::move(mid_last), std::move(last_it)};
                else
                    return {std::move(first), std::move(last_it)};
            }
        }
        else
        { // I は単なる前方イテレータです
            auto next_it = middle;
            do
            { // 最初のサイクルを回転させる
                ranges::iter_swap(first, next_it);
                ++first;
                ++next_it;
                if (first == middle)
                    middle = next_it;
            }
            while (next_it != last);
            auto new_first = first;
            while (middle != last)
            { // 後続のサイクルを回転
                next_it = middle;
                do
                {
                    ranges::iter_swap(first, next_it);
                    ++first;
                    ++next_it;
                    if (first == middle)
                        middle = next_it;
                }
                while (next_it != last);
            }
            return {std::move(new_first), std::move(middle)};
        }
    }
    template<ranges::forward_range R>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, ranges::iterator_t<R> middle) const
    {
        return (*this)(ranges::begin(r), std::move(middle), ranges::end(r));
    }
};
inline constexpr rotate_fn rotate {};

例

ranges::rotate は多くのアルゴリズムで共通して使用される基本構成要素です。この例では 挿入ソート を実演します。

#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
int main()
{
    std::string s(16, ' ');
    for (int k {}; k != 5; ++k)
    {
        std::iota(s.begin(), s.end(), 'A');
        std::ranges::rotate(s, s.begin() + k);
        std::cout << "Rotate left (" << k << "): " << s << '\n';
    }
    std::cout << '\n';
    for (int k {}; k != 5; ++k)
    {
        std::iota(s.begin(), s.end(), 'A');
        std::ranges::rotate(s, s.end() - k);
        std::cout << "Rotate right (" << k << "): " << s << '\n';
    }
    std::cout << "\nInsertion sort using `rotate`, step-by-step:\n";
    s = {'2', '4', '2', '0', '5', '9', '7', '3', '7', '1'};
    for (auto i = s.begin(); i != s.end(); ++i)
    {
        std::cout << "i = " << std::ranges::distance(s.begin(), i) << ": ";
        std::ranges::rotate(std::ranges::upper_bound(s.begin(), i, *i), i, i + 1);
        std::cout << s << '\n';
    }
    std::cout << (std::ranges::is_sorted(s) ? "Sorted!" : "Not sorted.") << '\n';
}

出力:

Rotate left (0): ABCDEFGHIJKLMNOP
Rotate left (1): BCDEFGHIJKLMNOPA
Rotate left (2): CDEFGHIJKLMNOPAB
Rotate left (3): DEFGHIJKLMNOPABC
Rotate left (4): EFGHIJKLMNOPABCD
Rotate right (0): ABCDEFGHIJKLMNOP
Rotate right (1): PABCDEFGHIJKLMNO
Rotate right (2): OPABCDEFGHIJKLMN
Rotate right (3): NOPABCDEFGHIJKLM
Rotate right (4): MNOPABCDEFGHIJKL
Insertion sort using `rotate`, step-by-step:
i = 0: 2420597371
i = 1: 2420597371
i = 2: 2240597371
i = 3: 0224597371
i = 4: 0224597371
i = 5: 0224597371
i = 6: 0224579371
i = 7: 0223457971
i = 8: 0223457791
i = 9: 0122345779
Sorted!

関連項目

要素の範囲をコピーして回転する
(アルゴリズム関数オブジェクト)
範囲内の要素の順序を反転する
(アルゴリズム関数オブジェクト)
範囲内の要素の順序を回転する
(関数テンプレート)