equal()
std::equal 是 C++ 标准库中的一个泛型算法,用于比较两个序列是否相等。这个算法会逐个比较两个序列中的元素,检查它们是否一一对应相等。如果所有元素都相等,并且两个序列的长度也相同,那么这两个序列就被认为是相等的。
以下是 std::equal 的基本语法:
template< class InputIt1, class InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2 );
template< class InputIt1, class InputIt2, class BinaryPredicate >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate p );
第一个版本接受两个范围的迭代器,分别是 first1 和 last1(表示第一个序列)以及 first2(表示第二个序列的开始)。它使用 operator== 来比较两个序列中的元素是否相等。
第二个版本类似于第一个,但额外接受一个二元谓词 p。这个二元谓词定义了如何比较两个序列中的元素。
std::equal 的返回值是一个布尔值,如果两个序列相等则返回 true,否则返回 false。
以下是一个使用 std::equal 的示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建两个序列
std::vector<int> sequence1 = {1, 2, 3, 4, 5};
std::vector<int> sequence2 = {1, 2, 3, 4, 5};
// 使用 equal 比较两个序列是否相等
bool areEqual = std::equal(sequence1.begin(), sequence1.end(), sequence2.begin());
if (areEqual) {
std::cout << "The sequences are equal." << std::endl;
} else {
std::cout << "The sequences are not equal." << std::endl;
}
return 0;
}
在这个示例中,sequence1 和 sequence2 是相等的,因此 std::equal 将返回 true,并输出 “The sequences are equal.”。如果两个序列不相等,例如 sequence2 的最后一个元素是 6 而不是 5,那么 std::equal 将返回 false,并输出 “The sequences are not equal.”。
注意,std::equal 只比较元素的值,而不关心序列中元素的顺序或它们在内存中的位置。此外,两个序列必须具有相同的长度,否则它们不会被认为是相等的。
std::equal 接受一个二元谓词 p 的版本允许你自定义两个元素如何被认为是相等的。这个二元谓词应该接受两个参数并返回一个布尔值,表示这两个参数是否应该被认为是相等的。
下面是一个使用 std::equal 的二元谓词版本的例子。在这个例子中,我们将比较两个 std::vectorstd::string 中的字符串,这些字符串在忽略大小写的情况下是否相等:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype> // 为了 std::tolower
// 自定义二元谓词,忽略大小写比较两个字符串
struct ignore_case_equal {
bool operator()(const std::string& str1, const std::string& str2) const {
if (str1.size() != str2.size()) {
return false;
}
for (size_t i = 0; i < str1.size(); ++i) {
if (std::tolower(str1[i]) != std::tolower(str2[i])) {
return false;
}
}
return true;
}
};
int main() {
// 创建两个字符串向量
std::vector<std::string> vec1 = {"Hello", "World", "!"};
std::vector<std::string> vec2 = {"hello", "world", "!"};
// 使用自定义的二元谓词比较两个向量是否相等(忽略大小写)
bool areEqual = std::equal(vec1.begin(), vec1.end(), vec2.begin(), ignore_case_equal());
if (areEqual) {
std::cout << "The vectors are equal (ignoring case)." << std::endl;
} else {
std::cout << "The vectors are not equal." << std::endl;
}
return 0;
}
在这个例子中,ignore_case_equal 是一个结构体,它定义了一个调用操作符 operator(),该操作符接受两个 std::string 参数并比较它们。比较是通过将每个字符串转换为小写并逐个字符地比较它们来实现的。如果所有字符都相等,那么这两个字符串就被认为是相等的(忽略大小写)。
std::equal 使用这个 ignore_case_equal 谓词来比较 vec1 和 vec2 中的字符串。由于 vec1 和 vec2 包含相同的单词(只是大小写不同),因此 std::equal 返回 true,并输出 “The vectors are equal (ignoring case).”。
请注意,std::equal 还要求两个序列的长度必须相等,否则它们不会被认为是相等的。
is_permutation()
std::is_permutation 是 C++ 标准库中的一个算法,用于检查一个序列是否可以通过重新排列另一个序列的元素来得到。换句话说,它检查两个序列是否包含相同的元素,而不管元素的顺序如何。
std::is_permutation 有两个版本:
- 不带二元谓词的版本,它使用 operator== 来比较元素。
- 带二元谓词的版本,它允许你自定义元素比较的逻辑。
std::is_permutation 不带谓词版本的例子相对简单,因为它直接使用 operator== 来比较元素。这意味着它要求两个序列中的元素类型和顺序都必须完全匹配。下面是一个使用不带谓词版本的 std::is_permutation 的例子:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建两个整数向量
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = {5, 4, 3, 2, 1};
// 检查两个向量是否是彼此的排列
bool arePermutations = std::is_permutation(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
if (arePermutations) {
std::cout << "The vectors are permutations of each other." << std::endl;
} else {
std::cout << "The vectors are not permutations of each other." << std::endl;
}
return 0;
}
在这个例子中,vec1 和 vec2 包含了相同的整数,但是顺序不同。由于 std::is_permutation 不带谓词版本只关心元素是否出现相同次数,而不关心顺序,因此它会返回 true,表示这两个向量是彼此的排列。程序将输出 “The vectors are permutations of each other.”。
如果 vec2 包含不同的元素或者元素数量不匹配,std::is_permutation 将返回 false,表示它们不是彼此的排列。例如,如果 vec2 是 {5, 4, 3, 2}(缺少一个 1),那么结果将是 false。
下面是使用带二元谓词的 std::is_permutation 的例子。在这个例子中,我们将比较两个字符串向量,检查它们是否包含相同的字符(忽略大小写):
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype> // 为了 std::tolower
// 自定义二元谓词,忽略大小写比较两个字符
struct ignore_case_compare {
bool operator()(char a, char b) const {
return std::tolower(a) == std::tolower(b);
}
};
int main() {
// 创建两个字符串向量
std::vector<char> vec1 = {'H', 'e', 'l', 'l', 'o'};
std::vector<char> vec2 = {'h', 'E', 'L', 'L', 'O'};
// 使用自定义的二元谓词检查两个向量是否是彼此的排列
bool arePermutations = std::is_permutation(vec1.begin(), vec1.end(), vec2.begin(), ignore_case_compare());
if (arePermutations) {
std::cout << "The vectors are permutations of each other (ignoring case)." << std::endl;
} else {
std::cout << "The vectors are not permutations of each other." << std::endl;
}
return 0;
}
在这个例子中,ignore_case_compare 是一个结构体,它定义了一个调用操作符 operator(),该操作符接受两个字符参数并比较它们转换为小写后的值。如果它们相等,则返回 true,表示这两个字符在忽略大小写的情况下是相等的。
std::is_permutation 使用这个 ignore_case_compare 谓词来比较 vec1 和 vec2 中的字符。由于 vec1 和 vec2 包含相同的字符(只是大小写不同),因此 std::is_permutation 返回 true,并输出 “The vectors are permutations of each other (ignoring case).”。
请注意,std::is_permutation 只会检查两个序列是否包含相同数量的每个元素,并且这些元素是否可以通过重新排列来匹配。它不会检查序列的长度是否相同,因为即使一个序列是另一个序列的子集,它们仍然可以是彼此的排列。如果需要检查长度,你应该在调用 std::is_permutation 之前手动进行。
mismatch()
std::mismatch 是 C++ 标准库中的一个泛型算法,用于查找两个序列中第一个不匹配的元素对。它有两个版本:一个不带谓词的版本和一个带二元谓词的版本。下面我将为这两个版本分别提供一个例子。
不带谓词的 std::mismatch 例子
这个版本的 std::mismatch 直接使用 operator== 来比较元素。它适用于元素类型支持相等比较的情况。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建两个整数向量
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = {1, 2, 3, 5, 5}; // 注意这里第四个元素与vec1不匹配
// 使用不带谓词的mismatch查找不匹配的元素对
auto mismatch_result = std::mismatch(vec1.begin(), vec1.end(), vec2.begin());
// mismatch_result 是一个包含两个迭代器的pair
// 这两个迭代器分别指向两个序列中第一个不匹配的元素
if (mismatch_result.first != vec1.end()) {
std::cout << "First mismatch found at positions: "
<< std::distance(vec1.begin(), mismatch_result.first) << " and "
<< std::distance(vec2.begin(), mismatch_result.second) << std::endl;
std::cout << "The elements are " << *mismatch_result.first << " and " << *mismatch_result.second << std::endl;
} else {
std::cout << "All elements match." << std::endl;
}
return 0;
}
在这个例子中,vec1 和 vec2 在第四个位置上的元素不匹配(vec1 是 4,而 vec2 是 5)。std::mismatch 返回了一个 std::pair<iterator, iterator>,其中第一个迭代器指向 vec1 中不匹配的元素,第二个迭代器指向 vec2 中不匹配的元素。程序输出这两个元素的位置和值。
带谓词的 std::mismatch 例子
这个版本的 std::mismatch 接受一个二元谓词,用于自定义元素比较的逻辑。
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义二元谓词,比较两个整数是否相差不超过一个给定的值
struct nearly_equal {
explicit nearly_equal(int difference) : diff(difference) {}
bool operator()(int a, int b) const {
return std::abs(a - b) <= diff;
}
private:
int diff;
};
int main() {
// 创建两个整数向量
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = {1, 3, 3, 4, 5}; // 注意这里第二个和第三个元素与vec1不近似相等(差值大于1)
// 使用带谓词的mismatch查找不近似相等的元素对,差值不超过1
auto mismatch_result = std::mismatch(vec1.begin(), vec1.end(), vec2.begin(), nearly_equal(1));
// 检查是否找到不匹配的元素对
if (mismatch_result.first != vec1.end()) {
std::cout << "First mismatch found at positions: "
<< std::distance(vec1.begin(), mismatch_result.first) << " and "
<< std::distance(vec2.begin(), mismatch_result.second) << std::endl;
std::cout << "The elements are " << *mismatch_result.first << " and " << *mismatch_result.second << std::endl;
} else {
std::cout << "All elements are nearly equal." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个名为 nearly_equal 的二元谓词,它接受一个整数 difference 作为构造函数的参数,并检查两个整数之间的差值的绝对值是否不超过 difference。我们使用这个谓词来查找 vec1 和 vec2 中不近似相等的元素对(即差值大于 1 的元素对)。程序输出第一个不近似相等元素对的位置和值。
lexicographical_compare()
std::lexicographical_compare 是一个泛型算法,用于比较两个序列的字典序。它适用于任何元素类型,只要该类型的比较操作符(operator<)是已定义的。std::lexicographical_compare 的基本版本接受两个序列的起始和结束迭代器,并返回一个布尔值,表示第一个序列是否在字典序上小于第二个序列。
下面是 std::lexicographical_compare 的基本版本的一个例子:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建两个字符串向量
std::vector<std::string> vec1 = {"apple", "banana", "cherry"};
std::vector<std::string> vec2 = {"apple", "blueberry", "cherry"};
// 使用lexicographical_compare比较两个向量
bool result = std::lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(), vec2.end());
// 输出比较结果
if (result) {
std::cout << "vec1 is lexicographically less than vec2" << std::endl;
} else {
std::cout << "vec1 is not lexicographically less than vec2" << std::endl;
}
return 0;
}
在这个例子中,vec1 和 vec2 都是字符串向量。std::lexicographical_compare 比较这两个向量,因为 banana 在字典序上小于 blueberry,所以 vec1 在字典序上小于 vec2,输出结果为 “vec1 is lexicographically less than vec2”。
std::lexicographical_compare 还有一个接受比较函数的版本,允许你提供自定义的比较逻辑。下面是一个使用自定义比较函数的例子:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义比较函数,用于比较两个字符串的长度
bool compare_by_length(const std::string& a, const std::string& b) {
return a.size() < b.size();
}
int main() {
// 创建两个字符串向量
std::vector<std::string> vec1 = {"apple", "banana", "cherry"};
std::vector<std::string> vec2 = {"apple", "blueberry", "cherry"};
// 使用lexicographical_compare和自定义比较函数比较两个向量
bool result = std::lexicographical_compare(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), compare_by_length);
// 输出比较结果
if (result) {
std::cout << "vec1 is lexicographically less than vec2 when comparing by length" << std::endl;
} else {
std::cout << "vec1 is not lexicographically less than vec2 when comparing by length" << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个比较函数 compare_by_length,它比较两个字符串的长度。然后我们将这个函数作为 std::lexicographical_compare 的第五个参数传递,告诉算法使用我们自定义的比较逻辑。因为 banana 的长度小于 blueberry 的长度,所以即使 banana 在字典序上大于 blueberry,使用自定义比较函数后,vec1 在长度比较上小于 vec2,输出结果为 “vec1 is lexicographically less than vec2 when comparing by length”。