std::is_permutation
来自cppreference.com
<tbody>
</tbody>
| 在标头 <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),第二个范围包含
std::distance(first1, last1)个元素。 - 对于重载 (3,4),第二个范围是
[first2,last2)。
1,3) 用
operator== 比较元素。2,4) 用给定的二元谓词
p 比较元素。如果 ForwardIt1 和 ForwardIt2 的值类型不同,那么程序非良构。
如果比较函数不是等价关系,那么行为未定义。
参数
| first1, last1 | - | 要比较的第一个元素范围的迭代器对 |
| first2, last2 | - | 要比较的第二个元素范围的迭代器对 |
| p | - | 若元素应被当做相等则返回 true 的二元谓词谓词函数的签名应等价于如下:
虽然签名不必有 |
| 类型要求 | ||
-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) 如果
InputIt1 和 InputIt2 都是老式随机访问迭代器 (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);
// 在 rest 上迭代,计数 [d_first, d_last) 中出现多少次
// 每个来自 [first, 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 << " 是 " << v1 << " 的排列:" << std::boolalpha
<< std::is_permutation(v1.begin(), v1.end(), v2.begin()) << '\n'
<< v3 << " 是 " << v1 << " 的排列:" << std::boolalpha
<< std::is_permutation(v1.begin(), v1.end(), v3.begin()) << '\n';
}
输出:
{ 3 5 4 1 2 } 是 { 1 2 3 4 5 } 的排列:true
{ 3 5 4 1 1 } 是 { 1 2 3 4 5 } 的排列:false
参阅
| 生成元素范围的下一个字典序更大的排列 (函数模板) | |
| 生成元素范围的下一个字典序更小的排列 (函数模板) | |
(C++20) |
指定 relation 施加等价关系 (概念) |
(C++20) |
判断一个序列是否为另一个序列的排列 (算法函数对象) |