定义于头文件 <algorithm>
算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first, last)
,其中 last
指代要查询或修改的最后元素的后一个元素。
判断一个序列是否为另一个序列的排列
std::is_permutation
template< class ForwardIt1, class ForwardIt2 > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2 ); | (1) | (C++11 起) (C++20 前) |
template< class ForwardIt1, class ForwardIt2 > constexpr bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2 ); | (C++20 起) | |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPredicate p ); | (2) | (C++11 起) (C++20 前) |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > constexpr bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPredicate p ); | (C++20 起) | |
template< class ForwardIt1, class ForwardIt2 > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2 ); | (3) | (C++14 起) (C++20 前) |
template< class ForwardIt1, class ForwardIt2 > constexpr bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2 ); | (C++20 起) | |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, | (4) | (C++14 起) (C++20 前) |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > constexpr bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, | (C++20 起) |
若存在范围 [first1, last1)
中元素的排列,使得该范围等于 [first2,last2)
,则返回 true ,若不给出,则其中 last2
代表 first2 + (last1 - first1) 。
1,3) 用 operator==
比较元素。若它不是等价关系则行为未定义。
2,4) 用给定的二元谓词 p
比较元素。若它不是等价关系则行为未定义。
参数
first1, last1 | - | 要比较的元素范围 |
first2, last2 | - | 要比较的第二范围 |
p | - | 若元素应被当做相等则返回 true 的二元谓词。 谓词函数的签名应等价于如下: bool pred(const Type &a, const Type &b);
|
类型要求 | ||
- ForwardIt1, ForwardIt2 必须满足遗留向前迭代器 (LegacyForwardIterator) 的要求。 | ||
- ForwardIt1, ForwardIt2 必须拥有相同的 value_type 。 |
返回值
若范围 [first1, last1)
是 [first2, last2)
的排列则为 true 。
复杂度
至多应用 O(N2) 次谓词,或若序列已经相等,则准确应用 N 次,其中 N=std::distance(first1, last1) 。
然而,若 ForwardIt1
和 ForwardIt2
满足遗留随机访问迭代器 (LegacyRandomAccessIterator) 的要求且 std::distance(first1, last1) != std::distance(first2, last2) ,则不应用谓词。
可能的实现
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 = d_first;
std::advance(d_last, 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;
}
调用示例
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <iterator>
#include <time.h>
using namespace std;
struct Cell
{
int x;
int y;
Cell &operator +=(const Cell &cell)
{
x += cell.x;
y += cell.y;
return *this;
}
bool operator <(const Cell &cell) const
{
if (x == cell.x)
{
return y < cell.y;
}
else
{
return x < cell.x;
}
}
bool operator ==(const Cell &cell) const
{
return x == cell.x && y == cell.y;
}
};
std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
os << "{" << cell.x << "," << cell.y << "}";
return os;
}
int main()
{
std::mt19937 g{std::random_device{}()};
srand((unsigned)time(NULL));;
std::cout << std::boolalpha;
auto func1 = []()
{
int n = std::rand() % 10 + 100;
Cell cell{n, n};
return cell;
};
// 初始化cells1
vector<Cell> cells1(3);
std::generate(cells1.begin(), cells1.end(), func1);
// 初始化cells2
vector<Cell> cells2(3);
std::generate(cells2.begin(), cells2.end(), func1);
// 1,3) 用 operator== 比较元素。若它不是等价关系则行为未定义。
size_t index = 0;
while (true)
{
// 打印cells1
std::cout << "cells1: ";
std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << " || ";
// 打印cells2
std::cout << "cells2: ";
std::copy(cells2.begin(), cells2.end(), std::ostream_iterator<Cell>(std::cout, " "));
if (std::is_permutation(cells1.begin(), cells1.end(), cells2.begin()))
{
std::cout << "is_permutation true" << std::endl;
break;
}
std::cout << "is_permutation false" << std::endl;
if (index > 6)
{
std::copy(cells1.begin(), cells1.end(), cells2.rbegin());
}
else
{
std::generate(cells2.begin(), cells2.end(), func1);
}
index++;
}
std::cout << std::endl << std::endl;
auto binPre = [](const Cell & a, const Cell & b)
{
return a.x == b.x && a.y == b.y;
};
// 初始化cells3
vector<Cell> cells3(3);
std::generate(cells3.begin(), cells3.end(), func1);
// 初始化cells4
vector<Cell> cells4(3);
std::generate(cells4.begin(), cells4.end(), func1);
// 2,4) 用给定的二元谓词 p 比较元素。若它不是等价关系则行为未定义。
index = 0;
while (true)
{
// 打印cells3
std::cout << "cells3: ";
std::copy(cells3.begin(), cells3.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << " || ";
// 打印cells4
std::cout << "cells4: ";
std::copy(cells4.begin(), cells4.end(), std::ostream_iterator<Cell>(std::cout, " "));
if (std::is_permutation(cells3.begin(), cells3.end(), cells4.begin(), binPre))
{
std::cout << "is_permutation true" << std::endl;
break;
}
std::cout << "is_permutation false" << std::endl;
if (index > 6)
{
std::copy(cells3.begin(), cells3.end(), cells4.rbegin());
}
else
{
std::generate(cells4.begin(), cells4.end(), func1);
}
index++;
}
return 0;
}
输出