#include <iostream>
#include <vector>
// write your code here......
#include<algorithm>
using namespace std;
int main() {
int num;
vector<int> v;
for (int i = 0; i < 5; i++) {
cin >> num;
v.push_back(num);
}
//自定义降序
sort(v.begin(),v.end(), [](int a, int b){return a > b;});
for_each(v.begin(), v.end(), [](int num){
cout<<num<<" ";
});
// write your code here......
return 0;
}
STL 排序 & 遍历算法 超详细使用指南(全场景示例,零基础易懂)
STL(标准模板库)的排序算法(核心是 sort)和遍历算法(核心是 for_each)是C++开发中最常用的工具,结合容器(如vector/array/list)使用能极大简化代码。下面分「排序算法」和「遍历算法」两部分讲解,包含语法、示例、注意事项,所有代码可直接运行!
一、STL 排序算法(核心:sort)
STL排序算法主要在 <algorithm> 头文件中(#include<algorithm>),其中 sort 是最常用的,另外补充 stable_sort(稳定排序)、list::sort(针对list容器)。
1. 核心特性
sort:不稳定排序(相等元素的相对位置可能改变),时间复杂度O(n log n),效率极高;stable_sort:稳定排序(相等元素相对位置不变),时间复杂度略高,适合需要保留相等元素顺序的场景;- 适用容器:
sort要求「随机访问迭代器」(vector/array/deque),list不能用std::sort,需用自身成员函数list.sort()。
2. 基础用法:默认升序排序
语法:sort(起始迭代器, 结束迭代器);
- 起始迭代器:容器第一个元素的迭代器(如
v.begin()); - 结束迭代器:容器尾后迭代器(如
v.end(),不指向任何元素,仅作为结束标志)。
示例(vector升序排序)
#include <iostream>
#include <vector>
#include <algorithm> // 排序算法必须包含此头文件
using namespace std;
int main() {
vector<int> v = {5, 2, 9, 1, 5, 6};
// 默认升序排序
sort(v.begin(), v.end());
// 遍历输出:1 2 5 5 6 9
for (int num : v) {
cout << num << " ";
}
return 0;
}
3. 自定义排序:降序/自定义规则
语法:sort(起始迭代器, 结束迭代器, 比较函数);比较函数可以是「lambda表达式(推荐)」「仿函数」「普通函数指针」,优先用lambda(简洁)。
示例1:降序排序(lambda)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {5, 2, 9, 1, 5, 6};
// 自定义降序排序(lambda表达式)
sort(v.begin(), v.end(), [](int a, int b) {
return a > b; // a > b 时,a排在b前面 → 降序
});
// 遍历输出:9 6 5 5 2 1
for (int num : v) {
cout << num << " ";
}
return 0;
}
示例2:对自定义类型排序(比如结构体)
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
// 自定义结构体:学生(姓名+分数)
struct Student {
string name;
int score;
};
int main() {
vector<Student> stu = {
{"张三", 85},
{"李四", 92},
{"王五", 78}
};
// 按分数降序排序(分数高的在前)
sort(stu.begin(), stu.end(), [](const Student& s1, const Student& s2) {
return s1.score > s2.score;
});
// 遍历输出
for (const auto& s : stu) {
cout << s.name << ":" << s.score << endl;
}
return 0;
}
输出:
李四:92 张三:85 王五:78
4. 特殊容器:list的排序(不能用std::sort)
list 是双向链表,无随机访问迭代器,因此不能用 std::sort,需用自身成员函数 list.sort():
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> l = {5, 2, 9, 1};
// list自带排序:默认升序
l.sort();
// 降序排序:l.sort(greater<int>());
// 遍历输出:1 2 5 9
for (int num : l) {
cout << num << " ";
}
return 0;
}
5. 稳定排序:stable_sort
当需要保留「相等元素的原始相对位置」时,用 stable_sort:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// 元素是pair:(值, 原始索引),演示稳定排序
vector<pair<int, int>> v = {{5,1}, {2,2}, {5,3}, {1,4}};
// 按第一个值升序,稳定排序(两个5的相对位置不变)
stable_sort(v.begin(), v.end(), [](const auto& a, const auto& b) {
return a.first < b.first;
});
// 输出:(1,4) (2,2) (5,1) (5,3)
for (auto& p : v) {
cout << "(" << p.first << "," << p.second << ") ";
}
return 0;
}
二、STL 遍历算法(核心:for_each)
STL遍历算法主要有 for_each(<algorithm> 头文件),另外补充C++11的「范围for循环」(最简洁)、「迭代器遍历」(兼容所有版本)。
1. 核心:for_each 算法
语法:for_each(起始迭代器, 结束迭代器, 处理函数);
- 处理函数:可以是普通函数「lambda表达式」「函数对象」,用于处理每个元素;
- 优势:代码模块化,处理逻辑可复用。
示例1:用lambda遍历并修改元素
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
// for_each遍历,每个元素+10(传引用修改原数据)
for_each(v.begin(), v.end(), [](int& num) {
num += 10;
cout << num << " "; // 输出:11 12 13 14
});
return 0;
}
示例2:用普通函数处理遍历逻辑(复用场景)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 自定义处理函数:打印元素并计算总和(用全局变量/引用传值)
int sum = 0;
void printAndSum(int num) {
cout << num << " ";
sum += num;
}
int main() {
vector<int> v = {1, 2, 3, 4};
// 调用for_each,传入函数名
for_each(v.begin(), v.end(), printAndSum);
cout << "\n总和:" << sum << endl; // 输出:总和:10
return 0;
}
2. 最简洁:范围for循环(C++11+,非算法但最常用)
语法:for(元素类型 变量 : 容器名) { 处理逻辑 }
- 优点:代码量最少、最易懂,日常开发99%场景用这个;
- 加
&可修改原元素,加const &只读(无拷贝开销)。
示例(只读遍历 + 修改遍历)
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
// 1. 只读遍历(const & 最优写法,无拷贝+安全)
cout << "原始数据:";
for (const auto& num : v) {
cout << num << " "; // 输出:1 2 3 4
}
// 2. 修改遍历(加&引用)
for (auto& num : v) {
num *= 2; // 每个元素×2
}
// 3. 再次遍历输出
cout << "\n修改后:";
for (const auto& num : v) {
cout << num << " "; // 输出:2 4 6 8
}
return 0;
}
3. 兼容所有版本:迭代器遍历
语法:用容器的迭代器(iterator/const_iterator)从 begin() 遍历到 end()。
- 适合:老旧编译器(C++11之前)、需要手动控制遍历步长的场景。
示例(正向/反向迭代器)
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
// 1. 正向迭代器(可读可写)
cout << "正向遍历:";
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // *it 解引用获取元素
}
// 2. 反向迭代器(从后往前)
cout << "\n反向遍历:";
for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
cout << *it << " "; // 输出:4 3 2 1
}
// 3. 常量迭代器(只读,不可修改)
cout << "\n常量遍历:";
for (vector<int>::const_iterator it = v.cbegin(); it != v.cend(); ++it) {
cout << *it << " ";
}
return 0;
}
4. 遍历算法对比:for_each vs 范围for
| 逻辑可复用、模块化 | 语法略长 | 处理逻辑需要复用的场景 |
范围for | 最简洁、易读、效率高 | 依赖C++11+ | 日常遍历(99%场景) |
迭代器遍历 | 兼容所有C++版本、可控步长 | 代码最长、易写错 | 老旧编译器、特殊遍历需求 |
三、综合示例:排序 + 遍历
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// 1. 初始化容器
vector<int> v = {9, 3, 7, 1, 5};
// 2. 排序:降序
sort(v.begin(), v.end(), [](int a, int b) {
return a > b;
});
// 3. 遍历:用for_each打印,同时计算总和
int sum = 0;
cout << "降序结果:";
for_each(v.begin(), v.end(), [&sum](int num) {
cout << num << " ";
sum += num;
});
// 4. 输出总和
cout << "\n总和:" << sum << endl; // 总和:25
return 0;
}
输出:
降序结果:9 7 5 3 1 总和:25
四、核心注意事项(避坑)
- 排序算法迭代器要求:
std::sort仅支持随机访问迭代器(vector/array/deque),list/set(set本身有序)不用; - 遍历修改元素必须加&:不管是范围for还是
for_each,修改元素时必须传引用(int&/auto&),否则只修改副本; - const_iterator不可修改:常量迭代器(
cbegin()/cend())只能读,不能修改元素; - sort默认升序:底层是
less<T>(),降序用greater<T>()或自定义lambda; - for_each不返回值:如需返回处理结果,可通过引用/全局变量传递(如示例中的总和)。
总结
- 排序:优先用
sort(默认升序,lambda自定义规则),list用list.sort(),稳定排序用stable_sort; - 遍历:日常优先用「范围for循环」(
for(const auto& x : v)),需要复用逻辑用for_each,老旧编译器用迭代器; - 核心原则:简洁优先,效率其次(STL算法效率已足够高,优先保证代码易读)。
掌握这两套算法,能覆盖99%的排序/遍历场景,是C++ STL的核心基础!

京公网安备 11010502036488号