文章目录
is_sorted()
std::is_sorted 是 C++ 标准库中的一个泛型算法,用于检查一个序列是否已按升序排序。它接受两个迭代器,分别表示序列的开始和结束,并返回一个布尔值,指示序列是否已排序。
下面是一个使用 std::is_sorted 的例子:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量并初始化
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用 is_sorted 检查向量是否已排序
bool isSorted = std::is_sorted(vec.begin(), vec.end());
// 输出检查结果
if (isSorted) {
std::cout << "The vector is sorted." << std::endl;
} else {
std::cout << "The vector is not sorted." << std::endl;
}
// 修改向量中的一个元素以使其不再排序
vec[2] = 0;
// 再次检查向量是否已排序
isSorted = std::is_sorted(vec.begin(), vec.end());
// 输出检查结果
if (isSorted) {
std::cout << "The vector is sorted." << std::endl;
} else {
std::cout << "The vector is not sorted." << std::endl;
}
return 0;
}
在这个例子中,我们首先创建了一个整数向量 vec 并初始化为升序排列。然后,我们使用 std::is_sorted 来检查这个向量是否已排序,由于它是升序排列的,所以输出将是 “The vector is sorted.”。
接下来,我们修改了向量中的一个元素,使其不再按升序排列。再次调用 std::is_sorted 检查向量时,这次它将返回 false,因此输出将是 “The vector is not sorted.”。
std::is_sorted 还有一个带自定义比较函数的版本,允许你提供自己的比较逻辑。这在你需要对非标准类型的序列进行排序检查时非常有用。下面是一个使用自定义比较函数的 std::is_sorted 的例子:
#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> vec = {"apple", "banana", "cherry", "blueberry"};
// 使用自定义比较函数检查向量是否已排序
bool isSorted = std::is_sorted(vec.begin(), vec.end(), compare_by_length);
// 输出检查结果
if (isSorted) {
std::cout << "The vector is sorted by length." << std::endl;
} else {
std::cout << "The vector is not sorted by length." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个比较函数 compare_by_length,它比较两个字符串的长度。然后,我们将这个函数作为第三个参数传递给 std::is_sorted,以检查向量是否按字符串长度升序排列。
is_sorted_until()
std::is_sorted_until 是 C++ 标准库中的一个泛型算法,它用于查找一个序列中第一个破坏排序顺序的元素。换句话说,它返回指向序列中第一个不满足排序条件的元素的迭代器。如果整个序列都是排序的,则它返回序列的尾迭代器。
这个算法对于确定一个序列的哪部分是有序的,而无需检查整个序列非常有用。
下面是使用 std::is_sorted_until 的一个例子:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量并初始化
std::vector<int> vec = {1, 2, 3, 5, 4, 6, 7, 8};
// 使用 is_sorted_until 查找第一个破坏排序顺序的元素
auto it = std::is_sorted_until(vec.begin(), vec.end());
// 输出结果
if (it != vec.end()) {
std::cout << "The first element that is out of order is: " << *it << std::endl;
} else {
std::cout << "The entire sequence is sorted." << std::endl;
}
// 输出从开始到破坏排序的元素之前的所有元素
for (auto elem = vec.begin(); elem != it; ++elem) {
std::cout << *elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,vec 是一个整数向量,其中第四个元素 5 破坏了升序排序。std::is_sorted_until 返回指向这个元素的迭代器,然后我们输出这个元素以及它之前的所有元素。
std::is_sorted_until 同样有一个接受自定义比较函数的版本,允许你提供自定义的比较逻辑来判定元素是否满足排序条件。以下是一个使用自定义比较函数的 std::is_sorted_until 的例子:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义比较函数,用于比较两个整数的绝对值
bool compare_absolute_value(int a, int b) {
return std::abs(a) < std::abs(b);
}
int main() {
// 创建一个整数向量并初始化
std::vector<int> vec = {-3, -1, 2, -4, 1, 5, -6};
// 使用 is_sorted_until 和自定义比较函数查找第一个破坏排序顺序的元素
auto it = std::is_sorted_until(vec.begin(), vec.end(), compare_absolute_value);
// 输出结果
if (it != vec.end()) {
std::cout << "The first element that is out of order (by absolute value) is: " << *it << std::endl;
} else {
std::cout << "The entire sequence is sorted by absolute value." << std::endl;
}
// 输出从开始到破坏排序的元素之前的所有元素
for (auto elem = vec.begin(); elem != it; ++elem) {
std::cout << *elem << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们定义了一个比较函数 compare_absolute_value,它比较两个整数的绝对值。然后,我们将这个函数作为 std::is_sorted_until 的第三个参数传递,以便算法使用这个自定义的比较逻辑来检查序列的排序状态。
is_partitioned()
std::is_partitioned 是 C++ 标准库中的一个泛型算法,用于检查一个序列是否根据给定的谓词(predicate)被划分成两部分。换句话说,这个算法检查序列是否可以从一个点开始被划分为两部分,使得在划分点之前的所有元素都满足谓词,而之后的元素都不满足谓词。
以下是 std::is_partitioned 的基本用法示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义谓词函数,检查一个整数是否小于 5
bool is_less_than_five(int n) {
return n < 5;
}
int main() {
// 创建一个整数向量
std::vector<int> vec = {1, 2, 3, 6, 7, 8};
// 使用 is_partitioned 检查向量是否根据谓词 is_less_than_five 被划分
bool result = std::is_partitioned(vec.begin(), vec.end(), is_less_than_five);
// 输出结果
if (result) {
std::cout << "The vector is partitioned according to the predicate." << std::endl;
} else {
std::cout << "The vector is not partitioned according to the predicate." << std::endl;
}
// 更改向量中的一个元素,使其不满足谓词
vec[2] = 6;
// 再次检查向量是否根据谓词被划分
result = std::is_partitioned(vec.begin(), vec.end(), is_less_than_five);
// 输出结果
if (result) {
std::cout << "The vector is partitioned according to the predicate." << std::endl;
} else {
std::cout << "The vector is not partitioned according to the predicate." << std::endl;
}
return 0;
}
在这个例子中,我们首先定义了一个谓词函数 is_less_than_five,它检查一个整数是否小于 5。然后,我们创建了一个整数向量 vec 并用 std::is_partitioned 检查它是否根据这个谓词被划分。由于 vec 的前三个元素(1, 2, 3)都小于 5,而后面的元素(6, 7, 8)都不小于 5,所以第一次调用 std::is_partitioned 返回 true。
接着,我们更改了 vec 的第三个元素为 6,这样它就不再满足谓词 is_less_than_five。因此,当我们再次调用 std::is_partitioned 时,它返回 false,因为序列现在不能被单一划分点划分为两部分,使得划分点之前的所有元素都满足谓词。
注意,std::is_partitioned 只检查是否存在这样的划分点,而不返回这个划分点的位置。如果你需要找到这个划分点的位置,可以使用 std::partition_point 算法。
partition_point()
std::partition_point 是 C++ 标准库中的一个泛型算法,它用于确定一个序列中满足特定谓词(predicate)的第一个元素的位置。这个算法常用于配合 std::partition 或 std::stable_partition 使用,这些算法会重新排列序列,使得满足谓词的元素出现在不满足谓词的元素之前。std::partition_point 则返回这个分界点的位置。
std::partition_point 的使用场景通常是在你已经对序列进行了划分操作后,想要知道划分点在哪里,而不必重新对整个序列进行划分。
下面是一个使用 std::partition_point 的例子:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义谓词函数,检查一个整数是否小于 5
bool is_less_than_five(int n) {
return n < 5;
}
int main() {
// 创建一个整数向量
std::vector<int> vec = {1, 2, 3, 6, 7, 8};
// 使用 partition 对向量进行划分,使得小于 5 的元素在前
std::partition(vec.begin(), vec.end(), is_less_than_five);
// 使用 partition_point 查找划分点的位置
auto partition_point_it = std::partition_point(vec.begin(), vec.end(), is_less_than_five);
// 输出划分点的位置
std::cout << "Partition point: " << std::distance(vec.begin(), partition_point_it) << std::endl;
// 输出划分点之前的所有元素
for (auto it = vec.begin(); it != partition_point_it; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们首先使用 std::partition 对 vec 进行划分,使得所有小于 5 的元素都出现在大于或等于 5 的元素之前。然后,我们使用 std::partition_point 查找划分点的位置,并输出它。最后,我们遍历并输出划分点之前的所有元素。
注意,std::partition 和 std::partition_point 都不会保证划分点之后的元素满足谓词或不满足谓词,它们只保证划分点之前的元素都满足谓词。如果你需要确保划分点之后的元素都不满足谓词,你可以使用 std::stable_partition 代替 std::partition。
is_heap()
std::is_heap 是 C++ 标准库中的一个泛型算法,用于检查给定范围的元素是否形成堆(Heap)。堆是一种特殊的树形数据结构,通常通过数组来实现,其中每个父节点的值都大于或等于(在最大堆中)或小于或等于(在最小堆中)其子节点的值。
std::is_heap 有两个版本:默认版本和自定义比较版本。
默认版本
默认版本的 std::is_heap 接受两个迭代器作为参数,分别表示要检查的序列的开始和结束。它返回一个布尔值,指示该序列是否形成一个有效的最大堆。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量并初始化为最大堆
std::vector<int> vec = {9, 5, 7, 3, 1};
// 使用 make_heap 将向量转换为最大堆
std::make_heap(vec.begin(), vec.end());
// 检查向量是否是一个有效的最大堆
bool isMaxHeap = std::is_heap(vec.begin(), vec.end());
// 输出检查结果
if (isMaxHeap) {
std::cout << "The vector is a valid max heap." << std::endl;
} else {
std::cout << "The vector is not a valid max heap." << std::endl;
}
return 0;
}
在这个例子中,我们首先创建了一个整数向量 vec 并初始化为一个序列。然后,我们使用 std::make_heap 将这个序列转换为一个最大堆。最后,我们使用 std::is_heap 检查转换后的向量是否仍然是一个有效的最大堆,并输出检查结果。
自定义比较版本
自定义比较版本的 std::is_heap 接受三个参数:两个迭代器表示要检查的序列的开始和结束,以及一个比较函数或可调用对象,用于定义堆的顺序。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义比较函数,用于定义最小堆的顺序
bool isLess(int a, int b) {
return a < b;
}
int main() {
// 创建一个整数向量并初始化为最小堆
std::vector<int> vec = {1, 3, 5, 7, 9};
// 使用自定义比较函数检查向量是否是一个有效的最小堆
bool isMinHeap = std::is_heap(vec.begin(), vec.end(), isLess);
// 输出检查结果
if (isMinHeap) {
std::cout << "The vector is a valid min heap." << std::endl;
} else {
std::cout << "The vector is not a valid min heap." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个自定义比较函数 isLess,用于检查一个整数是否小于另一个整数。然后,我们创建了一个整数向量 vec 并初始化为一个最小堆。最后,我们使用 std::is_heap 和自定义比较函数检查这个向量是否仍然是一个有效的最小堆,并输出检查结果。
is_heap_until()
std::is_heap_until 是 C++ 标准库中的一个泛型算法,用于确定给定范围内的元素序列保持堆性质的最后位置。换句话说,它会找到最后一个违反堆性质的元素,并返回指向该元素之后的位置的迭代器。如果整个序列都是有效的堆,那么它将返回范围的末尾迭代器。
std::is_heap_until 有两个版本:默认版本和自定义比较版本。
默认版本
默认版本的 std::is_heap_until 接受两个迭代器作为参数,分别表示要检查的序列的开始和结束。它返回一个迭代器,指向保持堆性质的最后一个元素之后的位置。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量并初始化为最大堆
std::vector<int> vec = {9, 5, 7, 3, 1, 2, 6};
// 假设 vec 的前五个元素是有效的最大堆
// 使用 is_heap_until 查找违反堆性质的第一个元素
auto it = std::is_heap_until(vec.begin(), vec.end());
// it 现在指向第一个违反堆性质的元素,即 vec[5]
// 输出结果
std::cout << "The sequence is a valid heap until position: "
<< std::distance(vec.begin(), it) << std::endl;
return 0;
}
在这个例子中,我们创建了一个包含七个元素的整数向量 vec。假设前五个元素(9, 5, 7, 3, 1)是一个有效的最大堆,但从第六个元素开始,堆性质被破坏了(因为 1 大于 2)。std::is_heap_until 将返回指向第六个元素(即 2)的迭代器,因为这个元素是第一个违反堆性质的元素。
自定义比较版本
自定义比较版本的 std::is_heap_until 接受三个参数:两个迭代器表示要检查的序列的开始和结束,以及一个比较函数或可调用对象,用于定义堆的顺序。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义比较函数,用于定义最小堆的顺序
bool isLess(int a, int b) {
return a < b;
}
int main() {
// 创建一个整数向量并初始化为最小堆
std::vector<int> vec = {1, 3, 5, 7, 9, 2, 6};
// 假设 vec 的前五个元素是有效的最小堆
// 使用自定义比较函数和 is_heap_until 查找违反堆性质的第一个元素
auto it = std::is_heap_until(vec.begin(), vec.end(), isLess);
// it 现在指向第一个违反堆性质的元素,即 vec[5]
// 输出结果
std::cout << "The sequence is a valid heap until position: "
<< std::distance(vec.begin(), it) << std::endl;
return 0;
}
在这个例子中,我们定义了一个自定义比较函数 isLess,用于检查一个整数是否小于另一个整数。然后,我们创建了一个包含七个元素的整数向量 vec,并假设前五个元素(1, 3, 5, 7, 9)是一个有效的最小堆。从第六个元素开始,堆性质被破坏了(因为 9 小于 2)。使用自定义比较函数和 std::is_heap_until,我们可以找到第一个违反最小堆性质的元素(即 2),并输出其位置。
all_of()
std::all_of 是 C++ 标准库中的一个算法,它用于检查给定范围内的所有元素是否都满足某个条件。该算法接受一个范围(由两个迭代器定义)和一个断言函数或可调用对象,然后应用该断言函数到范围中的每个元素,并检查是否所有元素都使断言函数返回 true。如果所有元素都满足条件,则 std::all_of 返回 true,否则返回 false。
默认版本
默认版本的 std::all_of 使用给定的断言函数或 lambda 表达式来检查范围内的所有元素。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用 std::all_of 检查所有元素是否都大于 0
bool allPositive = std::all_of(numbers.begin(), numbers.end(), [](int n) {
return n > 0;
});
// 输出结果
if (allPositive) {
std::cout << "All numbers are positive." << std::endl;
} else {
std::cout << "There are negative numbers." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否大于 0。std::all_of 应用这个 lambda 表达式到 numbers 向量中的每个元素,并因为所有元素都大于 0,所以返回 true。
自定义断言版本
你也可以提供一个自定义的断言函数作为 std::all_of 的第三个参数。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义断言函数,检查一个整数是否是偶数
bool isEven(int n) {
return n % 2 == 0;
}
int main() {
// 创建一个整数向量
std::vector<int> numbers = {2, 4, 6, 8, 10};
// 使用自定义断言函数检查所有元素是否都是偶数
bool allEven = std::all_of(numbers.begin(), numbers.end(), isEven);
// 输出结果
if (allEven) {
std::cout << "All numbers are even." << std::endl;
} else {
std::cout << "There are odd numbers." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个名为 isEven 的函数,它检查一个整数是否是偶数。然后,我们将这个函数作为 std::all_of 的第三个参数,以检查 numbers 向量中的所有元素是否都是偶数。因为所有元素都是偶数,所以 std::all_of 返回 true。
这两种版本(默认和自定义断言)的用法都非常灵活,可以根据需要选择使用 lambda 表达式还是自定义函数来定义检查条件
any_of()
std::any_of 是 C++ 标准库中的一个算法,用于检查给定范围内的元素是否满足某个条件。这个算法会应用一个断言函数或可调用对象到范围中的每个元素,并返回 true 一旦找到使断言函数返回 true 的元素,否则如果范围中的所有元素都不满足条件,则返回 false。
std::any_of 有两个版本:默认版本和自定义断言版本。
默认版本
默认版本的 std::any_of 接受两个迭代器表示范围的开始和结束,以及一个断言函数或可调用对象。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用 std::any_of 检查是否有任何元素是偶数
bool hasEven = std::any_of(numbers.begin(), numbers.end(), [](int n) {
return n % 2 == 0;
});
// 输出结果
if (hasEven) {
std::cout << "There are even numbers in the range." << std::endl;
} else {
std::cout << "There are no even numbers in the range." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否是偶数。std::any_of 应用这个 lambda 表达式到 numbers 向量中的每个元素,一旦找到至少一个偶数,就返回 true。
自定义断言版本
你也可以提供一个自定义的断言函数作为 std::any_of 的第三个参数。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义断言函数,检查一个整数是否大于某个值
bool isGreaterThanThree(int n) {
return n > 3;
}
int main() {
// 创建一个整数向量
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用自定义断言函数检查是否有任何元素大于3
bool hasGreaterThanThree = std::any_of(numbers.begin(), numbers.end(), isGreaterThanThree);
// 输出结果
if (hasGreaterThanThree) {
std::cout << "There are numbers greater than 3 in the range." << std::endl;
} else {
std::cout << "There are no numbers greater than 3 in the range." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个名为 isGreaterThanThree 的函数,它检查一个整数是否大于 3。然后,我们将这个函数作为 std::any_of 的第三个参数,以检查 numbers 向量中是否有任何元素大于 3。因为 4 和 5 都大于 3,所以 std::any_of 返回 true。
这两种版本(默认和自定义断言)的用法都非常灵活,可以根据需要选择使用 lambda 表达式还是自定义函数来定义检查条件。
none_of()
std::none_of 是 C++ 标准库中的一个算法,用于检查给定范围内的元素是否都不满足某个条件。换句话说,它验证是否没有一个元素使给定的断言函数或可调用对象返回 true。如果范围内没有元素满足条件,std::none_of 返回 true,否则返回 false。
默认版本
默认版本的 std::none_of 接受两个迭代器表示范围的开始和结束,以及一个断言函数或可调用对象。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 创建一个整数向量
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用 std::none_of 检查是否没有任何元素是偶数
bool noEvenNumbers = std::none_of(numbers.begin(), numbers.end(), [](int n) {
return n % 2 == 0;
});
// 输出结果
if (noEvenNumbers) {
std::cout << "There are no even numbers in the range." << std::endl;
} else {
std::cout << "There are even numbers in the range." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否是偶数。std::none_of 应用这个 lambda 表达式到 numbers 向量中的每个元素。因为 numbers 向量中至少有一个元素(即 2)是偶数,所以 std::none_of 返回 false。
自定义比较版本
你也可以提供一个自定义的比较函数作为 std::none_of 的第三个参数。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
// 自定义比较函数,检查一个整数是否小于等于 3
bool isLessThanOrEqualToThree(int n) {
return n <= 3;
}
int main() {
// 创建一个整数向量
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用自定义比较函数检查是否没有任何元素小于等于 3
bool noElementLessThanOrEqualToThree = std::none_of(numbers.begin(), numbers.end(), isLessThanOrEqualToThree);
// 输出结果
if (noElementLessThanOrEqualToThree) {
std::cout << "There are no numbers less than or equal to 3 in the range." << std::endl;
} else {
std::cout << "There are numbers less than or equal to 3 in the range." << std::endl;
}
return 0;
}
在这个例子中,我们定义了一个名为 isLessThanOrEqualToThree 的函数,它检查一个整数是否小于或等于 3。然后,我们将这个函数作为 std::none_of 的第三个参数,以检查 numbers 向量中是否有任何元素小于或等于 3。因为 numbers 向量中有多个元素(即 1、2、3)满足这个条件,所以 std::none_of 返回 false。
这两个版本(默认和自定义比较)都允许你灵活地使用 lambda 表达式或自定义函数来定义检查条件,以便确定范围内是否有元素满足该条件。