C++11 在标准库中引入了一系列新的算法,这些新增的算法使我们的代码写起来更简洁方便。
下面是 C++11 中新增加的一些重要算法的简要描述和使用方法:
1、非修改序列操作
std::all_of
:检查范围内的所有元素是否都满足指定的谓词。std::any_of
:检查范围内是否存在满足指定谓词的元素。std::none_of
:检查范围内是否没有元素满足指定的谓词。std::find_if_not
:在范围内查找不满足指定谓词的第一个元素,这个算法和已经存在的std::find_if
是相反的。
代码示例
以下的示例代码用来演示使用上面这些算法检查容器中元素的属性。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 初始化一个整数向量
std::vector<int> numbers = {2, 4, 6, 8, 10, 12};
// 检查所有元素是否都是偶数
bool allEven = std::all_of(numbers.begin(), numbers.end(), [](int x) {
return x % 2 == 0;
});
std::cout << "All elements are even: " << std::boolalpha << allEven << std::endl;
// 检查是否存在大于10的元素
bool anyGreaterThanTen = std::any_of(numbers.begin(), numbers.end(), [](int x) {
return x > 10;
});
std::cout << "Any element greater than 10: " << anyGreaterThanTen << std::endl;
// 检查是否没有元素小于0
bool noneLessThanZero = std::none_of(numbers.begin(), numbers.end(), [](int x) {
return x < 0;
});
std::cout << "No elements less than 0: " << noneLessThanZero << std::endl;
// 查找第一个不是偶数的元素
auto it = std::find_if_not(numbers.begin(), numbers.end(), [](int x) {
return x % 2 == 0;
});
if (it != numbers.end()) {
std::cout << "First element not even: " << *it << std::endl;
} else {
std::cout << "All elements are even" << std::endl;
}
return 0;
}
输出:
All elements are even: true
Any element greater than 10: true
No elements less than 0: true
All elements are even
2、修改序列操作
std::copy_if
:复制满足指定条件的元素到另一个容器。std::move
:将元素从一个容器移动到另一个容器(move),而非拷贝(copy)。std::move_backward
:类似std::move
,但是从范围的末尾开始操作,适合某些特定的容器操作。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 6, 3, 8, 5, 7, 2, 9};
std::vector<int> copied;
std::vector<int> moved(8); // 预分配空间以便使用std::move_backward
// 1. 使用std::copy_if复制所有大于5的元素
std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(copied), [](int n) { return n > 5; });
std::cout << "Copied elements: ";
for (auto n : copied) std::cout << n << " ";
std::cout << "\n";
// 2. 使用std::move将numbers的元素移动到另一个向量
std::vector<int> movedNumbers(std::make_move_iterator(numbers.begin()), std::make_move_iterator(numbers.end()));
std::cout << "Moved elements: ";
for (auto n : movedNumbers) std::cout << n << " ";
std::cout << "\nOriginal vector (now empty elements): ";
for (auto n : numbers) std::cout << n << " "; // 注意:numbers的元素现在处于未定义状态
std::cout << "\n";
// 3. 使用 std::move_backward,移动前 6 个元素
std::move_backward(movedNumbers.begin(), std::next(movedNumbers.begin(), 6), moved.end());
std::cout << "Elements after move_backward: ";
for (auto n : moved) std::cout << n << " ";
std::cout << "\n";
return 0;
}
输出:
Copied elements: 6 8 7 9
Moved elements: 1 6 3 8 5 7 2 9
Original vector (now empty elements): 1 6 3 8 5 7 2 9
Elements after move_backward: 0 0 1 6 3 8 5 7
注意第 2 步操作,我们使用 make_move_iterator
创建两个 move_iterator,如果使用下面这个语句:
std::vector<int> copiedNumbers(numbers.begin(), numbers.end());
将不会使用移动方式,而是将数值拷贝到 copiedNumbers。
3、排序和相关操作
std::is_partitioned
:检查给定范围是否被分割成两个满足特定条件的子序列。std::partition_copy
:根据谓词将元素分割并复制到两个不同的容器。std::partition_point
:找到分割序列的分界点。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::vector<int> numbers = {1, 9, 3, 8, 5, 7, 2, 6};
// 先对向量进行分区
std::partition(numbers.begin(), numbers.end(), [](int n) { return n > 5; });
std::cout << "Partitioned: ";
for(auto n : numbers) std::cout << n << " ";
std::cout << std::endl;
// 检查是否已分区
bool partitioned = std::is_partitioned(numbers.begin(), numbers.end(), [](int n) { return n > 5; });
std::cout << "Is partitioned: " << std::boolalpha << partitioned << "\n";
std::vector<int> less_than_6, greater_than_5;
// 复制分区元素
std::partition_copy(numbers.begin(), numbers.end(), std::back_inserter(greater_than_5), std::back_inserter(less_than_6),
[](int n) { return n > 5; });
std::cout << "Elements greater than 5: ";
for (auto n : greater_than_5) std::cout << n << " ";
std::cout << "\nElements not greater than 5: ";
for (auto n : less_than_6) std::cout << n << " ";
std::cout << "\n";
// 查找分区点
auto partitionPoint = std::partition_point(numbers.begin(), numbers.end(), [](int n) { return n > 5; });
std::cout << "Partition point at: " << *partitionPoint << "\n";
return 0;
}
输出:
Partitioned: 6 9 7 8 5 3 2 1
Is partitioned: true
Elements greater than 5: 6 9 7 8
Elements not greater than 5: 5 3 2 1
Partition point at: 5
4、数值操作
std::iota
:在给定范围内填充递增序列,从而生成有序序列。
代码示例
std::iota
定义在<numeric>
头文件中。
#include <iostream>
#include <vector>
#include <numeric> // 包含 std::iota
int main() {
std::vector<int> numbers(10); // 创建一个大小为10的vector
// 使用std::iota填充numbers,使其元素从0开始递增
std::iota(numbers.begin(), numbers.end(), 0);
// 输出填充后的vector
std::cout << "The vector contains: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 用std::iota生成另一个序列,此时起始值为10
std::iota(numbers.begin(), numbers.end(), 10);
// 输出新的序列
std::cout << "After reassigning, the vector contains: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
输出:
The vector contains: 0 1 2 3 4 5 6 7 8 9
After reassigning, the vector contains: 10 11 12 13 14 15 16 17 18 19
5、堆操作
std::is_heap
:检查给定范围是否形成一个堆。std::is_heap_until
:找到给定范围中不满足堆性质的第一个位置。std::make_heap
、std::push_heap
、std::pop_heap
、std::sort_heap
:虽然这些函数在 C++11 之前就存在,但 C++11 对它们进行了优化和改进,提高了与新特性的兼容性。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 初始化一个未排序的整数向量
std::vector<int> numbers = {4, 1, 3, 5, 2, 9, 7, 8, 6};
// 使用std::make_heap将向量转换为最大堆
std::make_heap(numbers.begin(), numbers.end());
std::cout << "After make_heap, numbers: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 检查是否为堆
bool isHeap = std::is_heap(numbers.begin(), numbers.end());
std::cout << "Is the vector a heap? " << std::boolalpha << isHeap << std::endl;
// 向堆中添加新元素
numbers.push_back(10);
std::push_heap(numbers.begin(), numbers.end()); // 重新调整为堆
std::cout << "After push_heap, numbers: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 从堆中移除根元素
std::pop_heap(numbers.begin(), numbers.end()); // 将最大元素移至末尾
numbers.pop_back(); // 实际移除元素
std::cout << "After pop_heap, numbers: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 对堆进行排序
std::sort_heap(numbers.begin(), numbers.end());
std::cout << "After sort_heap, numbers: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 使用std::is_heap_until找到不是堆的第一个位置
auto heapEnd = std::is_heap_until(numbers.begin(), numbers.end());
std::cout << "The range is a heap until element: ";
std::cout << (heapEnd - numbers.begin()) << std::endl;
return 0;
}
输出:
After make_heap, numbers: 9 8 7 6 2 3 4 5 1
Is the vector a heap? true
After push_heap, numbers: 10 9 7 6 8 3 4 5 1 2
After pop_heap, numbers: 9 8 7 6 2 3 4 5 1
After sort_heap, numbers: 1 2 3 4 5 6 7 8 9
The range is a heap until element: 1
6、最小/最大操作
std::minmax
:同时返回给定值中的最小值和最大值。std::minmax_element
:返回给定范围中的最小元素和最大元素的迭代器。
代码示例
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
// 使用std::minmax对一组值进行操作
auto result = std::minmax({1, 3, 5, 7, 9, 2, 4, 6, 8, 0});
std::cout << "The min value is: " << result.first << std::endl;
std::cout << "The max value is: " << result.second << std::endl;
// 使用std::minmax_element对容器中的元素进行操作
std::vector<int> numbers = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
auto minmaxPair = std::minmax_element(numbers.begin(), numbers.end());
if (minmaxPair.first != numbers.end() && minmaxPair.second != numbers.end()) {
std::cout << "The smallest element in the vector is: " << *minmaxPair.first << std::endl;
std::cout << "The largest element in the vector is: " << *minmaxPair.second << std::endl;
}
return 0;
}
输出将显示:
The min value is: 0
The max value is: 9
The smallest element in the vector is: 0
The largest element in the vector is: 9
总结
这些新增的算法增强了 C++ 的标准库,为开发者提供了更多的工具来编写高效和简洁的代码。
通过利用这些算法,可以减少手写的代码量,同时也可以保证代码的性能和可读性。