Namespaces
Variants

std::is_permutation

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

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


 
ヘッダ<algorithm>
template< class ForwardIt1, class ForwardIt2 >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2 );
で定義 (1) (C++11 から)
(C++20 から constexpr)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, BinaryPredicate p );
(2) (C++11 から)
(C++20 から constexpr)
template< class ForwardIt1, class ForwardIt2 >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2 );
(3) (C++14 から)
(C++20 から constexpr)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2,
                     BinaryPredicate p );
(4) (C++14 から)
(C++20 から constexpr)

[first1, last1) が 順列 であるかどうかをチェックします。範囲は first2 から始まります:

  • オーバーロード (1,2) では、2番目の範囲は std::distance(first1, last1) 個の要素を持ちます。
  • オーバーロード (3,4) では、2番目の範囲は [first2, last2) です。
1,3) 要素の比較には operator== が使用されます。
2,4) 要素の比較には、指定された二項述語 p が使用されます。

もし ForwardIt1 と ForwardIt2 の 値型 が異なる場合、プログラムは不適格 (ill-formed) です。

比較関数が 同値関係 でない場合、動作は未定義です。

パラメータ

first1, last1 - 比較する最初の要素の範囲を定義するイテレータのペア
first2, last2 - 比較する2番目の要素の範囲を定義するイテレータのペア
p - 要素が等しいと扱われるべき場合に​ true を返す二項述語。

述語関数のシグネチャは以下と同等であるべき:

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

シグネチャが const & を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、 値カテゴリ に関係なく(したがって、 Type1 & は許可されない 、また Type1 Type1 に対してムーブがコピーと等価でない限り許可されない (C++11以降) )すべての Type1 と Type2 型の値を受け入れられなければならない。
型 Type1 と Type2 は、 InputIt1 と InputIt2 型のオブジェクトが間接参照可能であり、それぞれ Type1 と Type2 に暗黙的に変換可能でなければならない。 ​

型要件
-
ForwardIt1, ForwardIt2 は LegacyForwardIterator の要件を満たさなければならない。

戻り値

true 範囲 [ first1 , last1 ) が範囲 [ first2 , last2 ) の順列である場合、 false それ以外の場合。

計算量

与えられた N として std::distance(first1, last1):

1) 二つの範囲が等しい場合は正確に N 回の比較を operator== を用いて行い、そうでない場合は最悪で O(N2
)
回の比較を行う。
2) 二つの範囲が等しい場合は正確に N 回の述語の適用を p を用いて行い、そうでない場合は最悪で O(N2
)
回の適用を行う。
3,4) ForwardIt1 と ForwardIt2 が共に LegacyRandomAccessIterator であり、かつ last1 - first1 != last2 - first2 が true である場合、比較は行われない。
それ以外の場合:
3) 二つの範囲が等しい場合は正確に N 回の比較を operator== を用いて行い、そうでない場合は最悪で O(N2
)
回の比較を行う。
4) 二つの範囲が等しい場合は正確に N 回の述語の適用を p を用いて行い、そうでない場合は最悪で O(N2
)
回の適用を行う。

実装例

template<class ForwardIt1, class ForwardIt2>
bool is_permutation(ForwardIt1 first, ForwardIt1 last,
                    ForwardIt2 d_first)
{
    // 共通プレフィックスをスキップ
    std::tie(first, d_first) = std::mismatch(first, last, d_first);
    // 残りの要素を反復処理し、[first, last) の各要素が
    // [d_first, d_last) に何回出現するかをカウント
    if (first != last)
    {
        ForwardIt2 d_last = std::next(d_first, std::distance(first, last));
        for (ForwardIt1 i = first; i != last; ++i)
        {
            if (i != std::find(first, i, *i))
                continue; // この *i は既にチェック済み
            auto m = std::count(d_first, d_last, *i);
            if (m == 0 || std::count(i, last, *i) != m)
                return false;
        }
    }
    return true;
}

注記

std::is_permutationは、並べ替えアルゴリズム(例:ソート、シャッフル、パーティショニング)の正確性を検証するためにテストで使用できます。xが元の範囲でyが並べ替えられた範囲の場合、std::is_permutation(x, y)==trueは、yが「同じ」要素で構成されている(異なる位置にある可能性がある)ことを意味します。

例

#include <algorithm>
#include <iostream>
template<typename Os, typename V>
Os& operator<<(Os& os, const V& v)
{
    os << "{ ";
    for (const auto& e : v)
        os << e << ' ';
    return os << '}';
}
int main()
{
    static constexpr auto v1 = {1, 2, 3, 4, 5};
    static constexpr auto v2 = {3, 5, 4, 1, 2};
    static constexpr auto v3 = {3, 5, 4, 1, 1};
    std::cout << v2 << " is a permutation of " << v1 << ": " << std::boolalpha
              << std::is_permutation(v1.begin(), v1.end(), v2.begin()) << '\n'
              << v3 << " is a permutation of " << v1 << ": "
              << std::is_permutation(v1.begin(), v1.end(), v3.begin()) << '\n';
}

出力:

{ 3 5 4 1 2 } is a permutation of { 1 2 3 4 5 }: true
{ 3 5 4 1 1 } is a permutation of { 1 2 3 4 5 }: false

関連項目

要素範囲の辞書順で次に大きい順列を生成する
(関数テンプレート & アルゴリズム関数オブジェクト)
要素範囲の辞書順で次に小さい順列を生成する
(関数テンプレート & アルゴリズム関数オブジェクト)
は、relation が同値関係を課すことを
(コンセプト)
あるシーケンスが別のシーケンスの順列であるかどうかを判定する
(アルゴリズム関数オブジェクト)