<think>我们正在讨论C++中的<algorithm>头文件的使用方法。根据引用内容,我们知道这个头文件包含了大量用于操作序列的通用算法,如排序、反转、查找等。我将按照常见函数分类,结合示例代码进行讲解。
注意:由于用户明确要求使用中文,并且要求数学公式用$...$或$$...$$表示,我会在必要时使用LaTeX格式(比如在讲解算法复杂度时)。
主要函数分类如下:
1. 排序相关:sort, stable_sort, partial_sort
2. 查找相关:find, binary_search, lower_bound, upper_bound
3. 修改序列的操作:reverse, rotate, copy, fill, replace
4. 划分操作:partition
5. 数值运算:accumulate(注:accumulate在<numeric>中,但常与algorithm一起使用)
接下来,我将逐一介绍这些常用函数,并给出代码示例。
注意:所有示例代码都需要包含必要的头文件,特别是<algorithm>,以及<iostream>和<vector>(如果需要使用向量)。
一、排序函数
1. sort:对序列进行排序,默认升序。
函数签名:template< class RandomIt > void sort( RandomIt first, RandomIt last );
template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );
示例1:默认升序排序
```cpp
#include <iostream>
#include <vector>
#include <algorithm> // 包含sort
int main() {
std::vector<int> vec = {4, 2, 5, 1, 3};
// 对vec进行升序排序
std::sort(vec.begin(), vec.end());
// 输出:1 2 3 4 5
for (int num : vec)
std::cout << num << " ";
return 0;
}
```
示例2:降序排序(使用自定义比较函数)
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
bool cmp(int a, int b) {
return a > b; // 降序
}
int main() {
std::vector<int> vec = {4, 2, 5, 1, 3};
std::sort(vec.begin(), vec.end(), cmp);
// 或者使用lambda表达式:std::sort(vec.begin(), vec.end(), [](int a, int b){ return a > b; });
// 输出:5 4 3 2 1
for (int num : vec)
std::cout << num << " ";
return 0;
}
```
2. stable_sort:稳定排序,保持相等元素的相对顺序。
函数签名与sort类似。
二、查找函数
1. find:在序列中查找指定值,返回第一个匹配元素的迭代器,若找不到则返回end()。
函数签名:template< class InputIt, class T > InputIt find( InputIt first, InputIt last, const T& value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = std::find(vec.begin(), vec.end(), 3);
if (it != vec.end()) {
std::cout << "Found at position: " << std::distance(vec.begin(), it); // 输出:Found at position: 2
} else {
std::cout << "Not found";
}
return 0;
}
```
2. binary_search:在有序序列中二分查找指定值,返回是否存在。
函数签名:template< class ForwardIt, class T > bool binary_search( ForwardIt first, ForwardIt last, const T& value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5}; // 必须有序
bool found = std::binary_search(vec.begin(), vec.end(), 3);
std::cout << (found ? "Found" : "Not found"); // 输出:Found
return 0;
}
```
3. lower_bound:返回指向第一个不小于给定值的元素的迭代器(即第一个大于等于value的元素)。
函数签名:template< class ForwardIt, class T > ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 4, 4, 5}; // 有序
auto it = std::lower_bound(vec.begin(), vec.end(), 3);
// 第一个不小于3的元素是4,位置索引为2
if (it != vec.end()) {
std::cout << "First element not less than 3 is at position: " << std::distance(vec.begin(), it);
std::cout << ", value: " << *it; // 4
}
return 0;
}
```
4. upper_bound:返回指向第一个大于给定值的元素的迭代器。
函数签名:template< class ForwardIt, class T > ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 4, 4, 5}; // 有序
auto it = std::upper_bound(vec.begin(), vec.end(), 3);
// 第一个大于3的元素是4,位置索引为2
if (it != vec.end()) {
std::cout << "First element greater than 3 is at position: " << std::distance(vec.begin(), it);
std::cout << ", value: " << *it; // 4
}
return 0;
}
```
三、修改序列的操作
1. reverse:反转序列。
函数签名:template< class BidirIt > void reverse( BidirIt first, BidirIt last );
示例(引用[3]中的示例):
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> myvector;
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::reverse(myvector.begin(), myvector.end()); // 9 8 7 6 5 4 3 2 1
// 输出
for (auto it = myvector.begin(); it != myvector.end(); ++it)
std::cout << *it << ' ';
return 0;
}
```
2. rotate:旋转序列,将指定范围的元素移到序列前面。
函数签名:template< class ForwardIt > ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last );
示例:将vec中从第2个元素(下标1)开始到末尾的部分旋转到前面
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 旋转,使vec[1]成为第一个元素,vec[0]被移到后面
std::rotate(vec.begin(), vec.begin()+1, vec.end());
// 输出:2 3 4 5 1
for (int num : vec)
std::cout << num << " ";
return 0;
}
```
3. copy:复制序列。
函数签名:template< class InputIt, class OutputIt > OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst(5); // 预先分配空间
std::copy(src.begin(), src.end(), dst.begin());
for (int num : dst)
std::cout << num << " "; // 输出:1 2 3 4 5
return 0;
}
```
4. fill:将序列填充为指定值。
函数签名:template< class ForwardIt, class T > void fill( ForwardIt first, ForwardIt last, const T& value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec(5); // 5个元素的vector
std::fill(vec.begin(), vec.end(), 10); // 全部填充为10
for (int num : vec)
std::cout << num << " "; // 输出:10 10 10 10 10
return 0;
}
```
5. replace:将序列中特定值替换为新值。
函数签名:template< class ForwardIt, class T > void replace( ForwardIt first, ForwardIt last, const T& old_value, const T& new_value );
示例:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 2, 5};
std::replace(vec.begin(), vec.end(), 2, 20); // 将所有2替换成20
for (int num : vec)
std::cout << num << " "; // 输出:1 20 3 20 5
return 0;
}
```
四、划分操作
partition:根据谓词将序列分成两部分,满足谓词的元素排在前面,不满足的排在后面。不保留相对顺序(如果需要保留顺序,可用stable_partition)。
函数签名:template< class ForwardIt, class UnaryPredicate > ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );
示例:将偶数放在前面,奇数放在后面
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto it = std::partition(vec.begin(), vec.end(), [](int n){ return n % 2 == 0; });
// 输出:偶数部分:8 2 6 4 奇数部分:5 3 7 1 9(注意顺序可能改变)
std::cout << "Even: ";
for (auto i = vec.begin(); i != it; ++i)
std::cout << *i << " ";
std::cout << "\nOdd: ";
for (auto i = it; i != vec.end(); ++i)
std::cout << *i << " ";
return 0;
}
```
五、数值算法(<numeric>头文件,但常与<algorithm>一起使用)
accumulate:计算序列的累加值(或自定义二元操作的累积)。
函数签名:template< class InputIt, class T > T accumulate( InputIt first, InputIt last, T init );
template< class InputIt, class T, class BinaryOperation > T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );
示例1:求和
```cpp
#include <iostream>
#include <vector>
#include <numeric> // accumulate在此头文件中
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
int sum = std::accumulate(vec.begin(), vec.end(), 0); // 初始值为0
std::cout << sum; // 输出:15
return 0;
}
```
示例2:求积(使用自定义操作)
```cpp
#include <iostream>
#include <vector>
#include <numeric>
#include <functional> // 用于std::multiplies
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());
std::cout << product; // 输出:120 (1*2*3*4*5)
return 0;
}
```
最后,注意<algorithm>中还有其他很多有用的函数,如count, max_element, min_element, unique等。这里只列举了部分常用函数。
复杂度说明:
对于排序函数,sort的平均时间复杂度为$O(n \log n)$,最坏情况(如已经有序)可能达到$O(n^2)$(取决于实现,标准库通常实现为内省排序,可以保证$O(n \log n)$)。stable_sort的复杂度为$O(n \log n)$或$O(n \log^2 n)$,如果没有额外内存则后者。
reverse为$O(n)$,find为$O(n)$,binary_search为$O(\log n)$(前提是序列已排序)。
§§相关问题§§
1. 如何使用stable_sort保持相等元素的顺序?
2. 如何用partial_sort只对序列的前k个元素排序?
3. 如何使用unique函数去除相邻的重复元素?
4. 在partition操作后如何获取满足条件的元素个数?
5. 如何对自定义结构体使用sort函数?
</think>### C++ `<algorithm>` 常用函数详解
`<algorithm>` 是 C++ 标准库的核心算法头文件,提供高效、通用的序列操作函数。以下分类介绍关键函数及其使用方法:
---
#### 一、排序与重排函数
1. **`sort()`**
- **功能**:对序列进行排序(默认升序)
- **复杂度**:$O(n \log n)$
- **示例**:
```cpp
#include <algorithm>
#include <vector>
std::vector<int> vec = {5, 3, 1, 4, 2};
std::sort(vec.begin(), vec.end()); // 结果:1, 2, 3, 4, 5
```
- **自定义排序**(降序):
```cpp
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a > b; // 降序规则
});
```
2. **`reverse()`**
- **功能**:反转序列元素顺序
- **复杂度**:$O(n)$
- **示例**(引用[3]):
```cpp
std::vector<int> vec = {1, 2, 3, 4, 5};
std::reverse(vec.begin(), vec.end()); // 结果:5, 4, 3, 2, 1
```
---
#### 二、查找与判定函数
1. **`find()`**
- **功能**:在序列中查找指定值
- **复杂度**:$O(n)$
- **示例**:
```cpp
auto it = std::find(vec.begin(), vec.end(), 3);
if (it != vec.end())
std::cout << "Found at index: " << std::distance(vec.begin(), it);
```
2. **`binary_search()`**
- **功能**:在有序序列中二分查找
- **复杂度**:$O(\log n)$
- **前提**:序列必须已排序
```cpp
std::sort(vec.begin(), vec.end());
bool exists = std::binary_search(vec.begin(), vec.end(), 3);
```
---
#### 三、数值操作函数
1. **`min_element() / max_element()`**
- **功能**:查找最小/最大值
- **复杂度**:$O(n)$
- **示例**:
```cpp
auto min_it = std::min_element(vec.begin(), vec.end());
std::cout << "Min value: " << *min_it;
```
2. **`accumulate()`**(需 `<numeric>`)
- **功能**:计算序列累加和
- **示例**:
```cpp
#include <numeric>
int sum = std::accumulate(vec.begin(), vec.end(), 0);
```
---
#### 四、序列修改函数
1. **`copy()`**
- **功能**:复制序列到目标位置
- **示例**:
```cpp
std::vector<int> dest(5);
std::copy(vec.begin(), vec.end(), dest.begin());
```
2. **`replace()`**
- **功能**:替换指定值
- **示例**:
```cpp
std::replace(vec.begin(), vec.end(), 3, 99); // 将所有3替换为99
```
---
#### 五、关键特性与最佳实践
1. **迭代器泛型**
所有函数通过迭代器操作,支持多种容器(如 `vector`, `array`, `deque`):
```cpp
int arr[] = {9, 8, 7};
std::sort(std::begin(arr), std::end(arr)); // 数组排序
```
2. **性能优化**
- 优先用 `sort()` 替代 $O(n^2)$ 排序(如冒泡排序)
- 有序序列使用 `binary_search()` 替代 `find()`
3. **自定义规则扩展**
通过函数对象或 Lambda 实现灵活操作:
```cpp
// 按字符串长度排序
std::vector<std::string> words = {"cat", "apple", "dog"};
std::sort(words.begin(), words.end(), [](const auto& a, const auto& b) {
return a.size() < b.size(); // 结果: cat, dog, apple
});
```
---
### 常见问题解答
**Q1: 如何实现稳定排序?**
用 `stable_sort()` 替代 `sort()`,保留相等元素的原始顺序:
```cpp
std::stable_sort(vec.begin(), vec.end());
```
**Q2: 如何获取第 K 大元素?**
使用 `nth_element()` 部分排序:
```cpp
std::vector<int> vec = {5, 6, 2, 9, 1};
auto mid = vec.begin() + 2; // 获取第3大元素
std::nth_element(vec.begin(), mid, vec.end());
std::cout << *mid; // 输出:5
```
---