Namespaces
Variants

std::prev_permutation

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy、 ranges::sort、 ...
ソートと関連操作
分割操作
(C++11)    

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


 
ヘッダ <algorithm>
template< class BidirIt >
bool prev_permutation( BidirIt first, BidirIt last );
で定義 (1) (C++20 から constexpr)
template< class BidirIt, class Compare >
bool prev_permutation( BidirIt first, BidirIt last, Compare comp );
(2) (C++20 から constexpr)

範囲 [first, last) を前の 順列に変換します。そのような順列が存在する場合は true を返し、それ以外の場合は範囲を最後の順列 (降順) に変換して false を返します。

1) すべての順列の集合は、operator<(C++20 まで)std::less{}(C++20 から) に関して辞書順に並べられます。
2) すべての順列の集合は、comp に関して辞書順に並べられます。

の型が *first の (C++11 まで)Swappable ではなく (C++11 から)BidirItValueSwappable ではない場合、動作は未定義です。 目次

first, last

- 順列を生成する 範囲 を定義するイテレータのペア comp
- 比較関数オブジェクト ( Compare の要件を満たすオブジェクト)。第一引数が第二引数より小さいtrue場合に を返します。比較関数のシグネチャは以下と同等であるべきです:

シグネチャに

bool cmp(const Type1& a, const Type2& b);

が含まれている必要はありませんが、関数は渡されたオブジェクトを変更してはならず、型 (const の可能性がある) const& と Type1 のすべての値を (それらのType2値カテゴリに関わらず) 受け入れられなければなりません。したがって、 は許可されませんType1&。また、 は、Type1 の場合を除き許可されません (ムーブがコピーと同等の場合は許可される)Type1(C++11 から)。 型
と Type1 は、Type2 型のオブジェクトが逆参照可能であり、暗黙的に両方に変換可能である必要があります。 BidirIt型要件

-
は
BidirItValueSwappable と LegacyBidirectionalIterator の要件を満たさなければなりません。 戻り値

新しい順列が辞書順で古い順列より前にある場合、

true 。最初の順列に達し、範囲が最後の順列にリセットされた場合、false 。

例外

イテレータ操作または要素のスワップから投げられる例外。

計算量

N を std::distance(first, last) とすると:

1,2) 最大
N
2
回のスワップ。

実装例

template<class BidirIt>
bool prev_permutation(BidirIt first, BidirIt last)
{
    if (first == last)
        return false;
    BidirIt i = last;
    if (first == --i)
        return false;
    
    while (1)
    {
        BidirIt i1, i2;
        
        i1 = i;
        if (*i1 < *--i)
        {
            i2 = last;
            while (!(*--i2 < *i))
                ;
            std::iter_swap(i, i2);
            std::reverse(i1, last);
            return true;
        }
        
        if (i == first)
        {
            std::reverse(first, last);
            return false;
        }
    }
}

注記

順列の全シーケンスで平均すると、一般的な実装は呼び出しあたり約3回の比較と1.5回のスワップを行います。

実装 (例: MSVC STL) は、イテレータ型が LegacyContiguousIterator を満たし、その値型のスワップが非トリビアルな特殊メンバ関数や ADL により見つかる swap を呼び出さない場合にベクトル化を有効にすることがあります。

例

以下のコードは、文字列 "cab" の6つの順列をすべて逆順に出力します。

#include <algorithm>
#include <iostream>
#include <string>

int main()
{
    std::string s = "cab";
    
    do
    {
        std::cout << s << ' ';
    }
    while (std::prev_permutation(s.begin(), s.end()));
    
    std::cout << s << '\n';
}

出力:

cab bca bac acb abc cba

関連項目

シーケンスが別のシーケンスの順列であるかどうかを判定します
(関数テンプレート & アルゴリズム関数オブジェクト)
範囲の要素の次の辞書順に大きな順列を生成します
(関数テンプレート & アルゴリズム関数オブジェクト)
範囲の要素の次の辞書順に小さい順列を生成します
(アルゴリズム関数オブジェクト)