std::is_permutation
| ヘッダ <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)です。
operator== が使用されます。p が使用されます。もし ForwardIt1 と ForwardIt2 の 値型 が異なる場合、プログラムは不適格 (ill-formed) です。
比較関数が 同値関係 でない場合、動作は未定義です。
パラメータ
| first1, last1 | - | 比較する最初の要素の範囲を定義するイテレータのペア |
| first2, last2 | - | 比較する2番目の要素の範囲を定義するイテレータのペア |
| p | - |
要素が等しいと扱われるべき場合に
true
を返す二項述語。
述語関数のシグネチャは以下と同等であるべき: bool pred ( const Type1 & a, const Type2 & b ) ;
シグネチャが
const
&
を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、
値カテゴリ
に関係なく(したがって、
Type1
&
は許可されない
、また
Type1
|
| 型要件 | ||
-
ForwardIt1, ForwardIt2
は
LegacyForwardIterator
の要件を満たさなければならない。
|
||
戻り値
true
範囲
[
first1
,
last1
)
が範囲
[
first2
,
last2
)
の順列である場合、
false
それ以外の場合。
計算量
与えられた N として std::distance(first1, last1):
operator== を用いて行い、そうでない場合は最悪で O(N2) 回の比較を行う。
p を用いて行い、そうでない場合は最悪で O(N2) 回の適用を行う。
ForwardIt1 と ForwardIt2 が共に LegacyRandomAccessIterator であり、かつ last1 - first1 != last2 - first2 が true である場合、比較は行われない。operator== を用いて行い、そうでない場合は最悪で O(N2) 回の比較を行う。
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
関連項目
| 要素範囲の辞書順で次に大きい順列を生成する (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 要素範囲の辞書順で次に小さい順列を生成する (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
(C++20) |
は、relation が同値関係を課すことを (コンセプト) |
(C++20) |
あるシーケンスが別のシーケンスの順列であるかどうかを判定する (アルゴリズム関数オブジェクト) |