名前空間
変種
操作

std::prev_permutation

From cppreference.com
< cpp‎ | algorithm
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとRangeアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
実行ポリシー (C++17)
シーケンスを変更しない操作
一括操作
(C++17)
検索操作
(C++11)                (C++11)(C++11)

シーケンスを変更する操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートおよび関連操作
パーティション操作
ソート操作
二分探索操作
(パーティション化された範囲)
集合操作 (ソート済み範囲)
マージ操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作
prev_permutation

Cライブラリ
数値演算
未初期化メモリに対する操作
 
ヘッダー <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)

範囲 [firstlast) を、直前の順列に変換します。そのような順列が存在する場合は true を返します。存在しない場合は、範囲を最後の順列(std::sort の後に std::reverse を適用したかのように)に変換し、false を返します。

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

もし *first の型がSwappable ではない(C++11まで)BidirItValueSwappable ではない(C++11以降)場合、動作は未定義です。

目次

[編集] パラメータ

first, last - 順列を生成する要素の範囲を定義するイテレータのペア
comp - 比較関数オブジェクト(すなわち、Compareの要件を満たすオブジェクト)。最初の引数が2番目の引数より小さい場合にtrueを返す。

比較関数のシグネチャは、以下と同等でなければならない。

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

シグネチャにconst&は必須ではないが、関数は渡されたオブジェクトを変更してはならず、値カテゴリに関係なく、Type1Type2のすべての型(おそらくconst)の値を受け入れられなければならない(したがって、Type1&は許可されない。また、Type1のムーブがコピーと同等でない限り、Type1も許可されない(C++11以降))。
Type1 および Type2 の型は、BidirIt 型のオブジェクトを逆参照して、それらの両方に暗黙的に変換できる必要があります。

型要件
-
BidirIt は、ValueSwappable および LegacyBidirectionalIterator の要件を満たす必要があります。

[編集] 戻り値

新しい順列が辞書順で古い順列より前にある場合は true を返します。最初の順列に到達し、範囲が最後の順列にリセットされた場合は false を返します。

[編集] 例外

イテレータ操作または要素のスワップからスローされるすべての例外。

[編集] 計算量

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

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

[編集] 関連項目

あるシーケンスが別のシーケンスの順列であるかを判断する
(関数テンプレート) [編集]
要素の範囲の次に大きい辞書順の順列を生成する
(関数テンプレート) [編集]
要素の範囲の次に小さい辞書順の順列を生成する
(アルゴリズム関数オブジェクト)[編集]
English 日本語 中文(简体) 中文(繁體)