定义于头文件 <algorithm>
算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first, last)
,其中 last
指代要查询或修改的最后元素的后一个元素。
确定两个元素集合是否是相同的
std::equal
template< class InputIt1, class InputIt2 > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 ); | (1) | (C++20 前) |
template< class InputIt1, class InputIt2 > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 ); | (C++20 起) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2 ); | (2) | (C++17 起) |
template< class InputIt1, class InputIt2, class BinaryPredicate > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p ); | (3) | (C++20 前) |
template< class InputIt1, class InputIt2, class BinaryPredicate > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p ); | (C++20 起) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPredicate p ); | (4) | (C++17 起) |
template< class InputIt1, class InputIt2 > bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 ); | (5) | (C++14 起) (C++20 前) |
template< class InputIt1, class InputIt2 > constexpr bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 ); | (C++20 起) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2 ); | (6) | (C++17 起) |
template< class InputIt1, class InputIt2, class BinaryPredicate > bool equal( InputIt1 first1, InputIt1 last1, | (7) | (C++14 起) (C++20 前) |
template< class InputIt1, class InputIt2, class BinaryPredicate > constexpr bool equal( InputIt1 first1, InputIt1 last1, | (C++20 起) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPredicate > bool equal( ExecutionPolicy&& policy, ForwardIt1 first1, ForwardIt1 last1, | (8) | (C++17 起) |
1,3) 如果范围 [first1, last1)
和范围 [first2, first2 + (last1 - first1))
相等,返回 true ,否则返回 false
5,7) 如果范围 [first1, last1)
和范围 [first2, last2)
相等,返回 true ,否则返回 false
2,4,6,8) 同 (1,3,5,7) ,但按照 policy
执行。这些重载仅若 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> 为 true 才参与重载决议。
两个范围相等的条件是:对于范围 [first1, last1)
内的每个迭代器 i
, *i 等于 *(first2 + (i - first1)) 。重载形式 (1,2,5,6) 用 operator== 判定两个元素是否相等,而重载形式 (3,4,7,8) 用给定的谓词函数。
参数
first1, last1 | - | 进行比较的第一个范围 |
first2, last2 | - | 进行比较的第二个范围 |
p | - | 若元素应被当做相等则返回 true 的二元谓词。 谓词函数的签名应等价于如下: bool pred(const Type1 &a, const Type2 &b); 虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 |
类型要求 | ||
- InputIt1, InputIt2 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。 |
返回值
5-8) 如果范围 [first1, last1)
的长度不等于范围 [first2, last2)
的长度则返回 false 。
如果两个范围内的元素都相等,则返回 true 。
否则返回 false 。
注意
std::equal
不可应用到由 std::unordered_set 、 std::unordered_multiset 、 std::unordered_map 或 std::unordered_multimap 的迭代器构成的范围,因为即使此类容器存储相同的元素,在容器内元素存储的顺序也可能不同。
比较整个容器是否相等时,针对该容器的 operator==
重载通常是更好的选择。
复杂度
1,2) 最多 last1
- first1
次调用相应的谓词函数。
3,4) 最多 min(last1
- first1
, last2
- first2
) 次调用相应的谓词函数。
然而,若 InputIt1
和 InputIt2
满足遗留随机访问迭代器 (LegacyRandomAccessIterator) 的要求,且 last1 - first1 != last2 - first2 则不调用谓词函数。
异常
拥有名为 ExecutionPolicy
的模板形参的重载按下列方式报告错误:
- 若作为算法一部分调用的函数的执行抛出异常,且
ExecutionPolicy
为标准策略之一,则调用 std::terminate 。对于任何其他ExecutionPolicy
,行为是实现定义的。 - 若算法无法分配内存,则抛出 std::bad_alloc 。
可能的实现
版本一
template<class InputIt1, class InputIt2>
bool equal(InputIt1 first1, InputIt1 last1,
InputIt2 first2)
{
for (; first1 != last1; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return true;
}
版本二
template<class InputIt1, class InputIt2, class BinaryPredicate>
bool equal(InputIt1 first1, InputIt1 last1,
InputIt2 first2, BinaryPredicate p)
{
for (; first1 != last1; ++first1, ++first2) {
if (!p(*first1, *first2)) {
return false;
}
}
return true;
}
版本三
template<class InputIt1, class InputIt2>
bool equal(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2 )
{
if (distance(first1,last1) != distance(first2,last2)
return false;
for (; first1 != last1, first2 != last2; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return true;
}
版本四
template< class InputIt1, class InputIt2, class BinaryPredicate >
bool equal( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
BinaryPredicate p )
{
if (distance(first1,last1) != distance(first2,last2)
return false;
for (; first1 != last1, first2 != last2; ++first1, ++first2) {
if (!p(*first1, *first2)) {
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()
{
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(6);
std::generate(cells1.begin(), cells1.end(), func1);
// 打印cells1
std::cout << "cells1: ";
std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << "is palindrome: "
<< std::equal(cells1.begin(), cells1.begin() + cells1.size() / 2, cells1.rbegin())
<< std::endl;
std::cout << std::endl;
// 初始化cells2
vector<Cell> cells2{{101, 101}, {102, 102}, {103, 103}, {103, 103}, {102, 102}, {101, 101}};
std::cout << "cells2: ";
std::copy(cells2.begin(), cells2.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << "is palindrome: "
<< std::equal(cells2.begin(), cells2.begin() + cells2.size() / 2, cells2.rbegin())
<< std::endl;
std::cout << std::endl;
auto funcEqual = [](const Cell & a, const Cell & b)
{
return a.x == b.x && a.y == b.y;
};
// 初始化cells3
vector<Cell> cells3(6);
std::generate(cells3.begin(), cells3.end(), func1);
// 打印cells3
std::cout << "cells3: ";
std::copy(cells1.begin(), cells1.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << "is palindrome: "
<< std::equal(cells3.begin(), cells3.begin() + cells3.size() / 2, cells3.rbegin(), funcEqual)
<< std::endl;
std::cout << std::endl;
// 初始化cells4
vector<Cell> cells4{{105, 106}, {106, 107}, {108, 109}, {108, 109}, {106, 107}, {105, 106}};
std::cout << "cells4: ";
std::copy(cells4.begin(), cells4.end(), std::ostream_iterator<Cell>(std::cout, " "));
std::cout << std::endl;
std::cout << "is palindrome: "
<< std::equal(cells4.begin(), cells4.begin() + cells4.size() / 2, cells4.rbegin(), funcEqual)
<< std::endl;
return 0;
}