Namespaces
Variants

std::is_permutation

来自 zh.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起)
(constexpr 自C++20起)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, BinaryPredicate p );
(2) (自C++11起)
(constexpr 自C++20起)
template< class ForwardIt1, class ForwardIt2 >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2 );
(3) (自C++14起)
(constexpr 自C++20起)
template< class ForwardIt1, class ForwardIt2,
          class BinaryPredicate >
bool is_permutation( ForwardIt1 first1, ForwardIt1 last1,
                     ForwardIt2 first2, ForwardIt2 last2,
                     BinaryPredicate p );
(4) (自C++14起)
(constexpr 自C++20起)

检查 [first1, last1) 是否是一个 排列 的范围始于 first2:

  • 对于重载 (1,2),第二个范围包含 std::distance(first1, last1) 个元素。
  • 对于重载 (3,4),第二个范围是 [first2, last2)。
1,3) 元素使用 operator== 进行比较。
2,4) 元素使用给定的二元谓词 p 进行比较。

如果 ForwardIt1 和 ForwardIt2 具有不同的 值类型,则程序非良构。

如果比较函数不是一个 等价关系,则行为未定义。

参数

first1, last1 - 定义待比较第一个元素 范围 的迭代器对
first2, last2 - 定义待比较第二个元素 范围 的迭代器对
p - 二元谓词,若元素应被视为相等则返回​ true

谓词函数的签名应等价于如下形式:

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

虽然签名不必包含 const & ,但函数不得修改传递给它的对象,且必须能够接受所有(可能为 const 的) Type1 与 Type2 类型的值,无论其 值类别 为何(因此不允许 Type1 & ,也不允许 Type1 ,除非对于 Type1 移动等价于复制 (C++11 起) )。
类型 Type1 与 Type2 必须使得 InputIt1 与 InputIt2 类型的对象在解引用后能隐式转换到 Type1 和 Type2 respectively。 ​

类型要求
-
ForwardIt1, ForwardIt2 必须满足 LegacyForwardIterator 的要求。

返回值

当范围 [ first1 , last1 ) 是范围 [ first2 , last2 ) 的一个排列时返回 true ,否则返回 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

另见

生成元素范围的下一个按字典序更大的排列
(函数模板 & 算法函数对象)
生成元素范围的下一个按字典序更小的排列
(函数模板 & 算法函数对象)
指定一个 关系 构成等价关系
(概念)
确定一个序列是否为另一个序列的排列
(算法函数对象)