std::is_permutation
在标头 <algorithm> 定义
|
||
template< class ForwardIt1, class ForwardIt2 > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, |
(1) | (C++11 起) (C++20 起为 constexpr ) |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > |
(2) | (C++11 起) (C++20 起为 constexpr ) |
template< class ForwardIt1, class ForwardIt2 > bool is_permutation( ForwardIt1 first1, ForwardIt1 last1, |
(3) | (C++14 起) (C++20 起为 constexpr ) |
template< class ForwardIt1, class ForwardIt2, class BinaryPredicate > |
(4) | (C++14 起) (C++20 起为 constexpr ) |
检查 [
first1,
last1)
是否为 first2 开始的另一个范围的排列:
- 对于重载 (1,2),第二个范围包含 std::distance(first1, last1) 个元素。
- 对于重载 (3,4),第二个范围是
[
first2,
last2)
。
如果 ForwardIt1
和 ForwardIt2
的值类型不同,那么程序非良构。
如果比较函数不是等价关系,那么行为未定义。
参数
first1, last1 | - | 要比较的元素范围 |
first2, last2 | - | 要比较的第二范围 |
p | - | 若元素应被当做相等则返回 true 的二元谓词。 谓词函数的签名应等价于如下: bool pred(const Type1 &a, const Type2 &b); 虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 |
类型要求 | ||
-ForwardIt1, ForwardIt2 必须满足老式向前迭代器 (LegacyForwardIterator) 。
|
返回值
在范围 [
first1,
last1)
是 [
first2,
last2)
的排列时返回 true,否则返回 false。
复杂度
给定 N 为 std::distance(first1, last1):
) 次。
) 次。
InputIt1
和 InputIt2
都是老式随机访问迭代器 (LegacyRandomAccessIterator) ,并且 last1 - first1 != last2 - first2 是 true,那么不会进行任何比较。) 次。
) 次。
可能的实现
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) |
确定一个序列是否为另一序列的排列 (niebloid) |