- C++
讲解vector、list、迭代器、next_permutation、transform
- @ 2026-9-4 19:30:49
GESP5级零基础C++完整教程(基于PPT)
适合已经掌握基础语法(变量、循环、数组、函数)同学,讲解vector、list、迭代器、next_permutation、transform,附带真题完整注释代码。 头文件速记:
#include <vector>:vector容器#include <list>:list双向链表容器#include <algorithm>:sort、reverse、next_permutation、transform
第一部分 vector容器(动态数组,考试最高频)
vector = 动态数组,内存是连续一块空间,可以像数组下标访问;大小可以自动变化。
时间复杂度要点(必背)
- 随机访问
vec[0]、vec[5]: 很快 - 尾部push_back/pop_back:分摊
- 在中间/头部插入、删除元素:,需要移动大量元素
1.1 vector创建的3种写法
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//写法1:空vector,size=0,后面再添加元素
vector<int> a;
//写法2:5个元素,全部默认初始化为0
vector<int> b(5);
//写法3:5个元素,每个值等于42
vector<int> c(5, 42);
cout << b.size() << endl; // size() 获取里面元素个数 O(1)
return 0;
}
1.2 vector常用方法一览表 + 示例代码
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec;
vec.push_back(10); // push_back:在尾部增加元素 10
vec.push_back(20);
vec.push_back(30);
cout << vec.size() << endl; // 元素数量:3
cout << vec.empty() << endl; // empty() 判断是否为空,空返回true(1),否则false(0)
cout << vec[0] << endl; // 下标访问,和普通数组一样,不会检查越界
cout << vec.at(1) << endl; // at()访问,如果下标越界,程序会报错,更安全
cout << vec.front() << endl; // front() 获取第一个元素:10
cout << vec.back() << endl; // back() 获取最后一个元素:30
vec.pop_back(); // pop_back() 删除末尾元素,此时vec:{10,20}
// begin() 返回迭代器:指向第一个元素;end()指向最后元素的下一个位置
auto it = vec.begin();
cout << *it << endl; // *it 取出迭代器指向的值,输出10
vec.insert(vec.begin()+1, 99); // insert(迭代器位置,值) 在位置前面插入元素,vec:{10,99,20}
vec.clear(); // clear()清空全部元素,size变成0
return 0;
}
1.3 vector三种遍历方式
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {1,2,3,4,5};
//方式1:下标遍历(最简单,vector专属,list不能用下标!)
for(int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
//方式2:基于范围for循环(C++11,简洁)
for(auto num : v)
{
cout << num << " ";
}
cout << endl;
//方式3:迭代器遍历(vector、list通用!考试重点)
// auto it = v.begin() 迭代器相当于“智能指针”
for(auto it = v.begin(); it != v.end(); it++)
{
cout << *it << " "; // *it 获取迭代器指向的数据
}
cout << endl;
return 0;
}
1.4 sort、reverse算法(algorithm库)
⚠️注意:
sort(v.begin(),v.end())只可以用于vector,不能用于list!list有自己的.sort()成员函数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v = {5,2,4,1,3};
sort(v.begin(), v.end()); // 默认升序从小到大:1 2 3 4 5
for(auto x:v) cout << x << " ";
cout << endl;
reverse(v.begin(), v.end());// reverse反转序列:5 4 3 2 1
for(auto x:v) cout << x << " ";
return 0;
}
pair小知识点:pair<int,int>排序默认先比较first,first相等再比较second
vector<pair<int,int>> v;
v.push_back({3,2});
v.push_back({2,1});
v.push_back({5,1});
sort(v.begin(),v.end());
//排序结果 (2,1) (3,2) (5,1)
第二部分 list容器(双向链表)
头文件:#include <list>
底层是双向链表,内存不是连续存放。
必背时间复杂度
- 任意位置插入、删除:O(1),只要拿到迭代器
- 下标随机访问:O(n)!!list 不能写 lst[0],不支持下标!,只能用迭代器遍历
.size()老版本O(n),GESP考试记住PPT描述。
list常用操作
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> lst;
lst.push_back(10); //尾部插入
lst.push_front(5); //头部插入,vector没有push_front!
cout << lst.front() << endl; //取头元素5
cout << lst.back() << endl; //取尾元素10
lst.pop_back(); //删除末尾
lst.pop_front(); //删除头部
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
auto it = lst.begin();
it++; //移动迭代器到第二个元素
lst.insert(it, 99); //在it位置前面插入99
lst.erase(it); //删除it指向的元素
lst.sort(); //list自己的排序成员函数!!
// ❌ sort(lst.begin(),lst.end()); //错误!algorithm库sort不能用于list
//遍历list,只能用迭代器 / 范围for,不能下标
for(auto x : lst){
cout << x << " ";
}
return 0;
}
list迭代器倒序遍历:rbegin()反向开始,rend()反向结束
for(auto it = lst.rbegin(); it != lst.rend(); it++)
{
cout << *it << " ";
}
vector vs list对比总结(选择题高频)
| 特性 | vector(动态数组) | list(双向链表) |
|---|---|---|
| 内存 | 连续内存 | 链表分散内存 |
下标访问[i] |
✅支持 O(1) | ❌不支持 |
| 头部插入删除 | 慢 O(n) | 快 O(1) |
| 尾部插入删除 | 快 O(1) | |
| 中间插入删除 | 慢 O(n) | |
| 排序 | 用sort(begin,end) |
用成员函数.sort() |
第三部分 transform 变换函数(algorithm)
transform用来批量处理容器里面每一个元素。
形式1:一元运算,一个输入序列
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> nums = {1,2,3,4};
vector<int> squared(nums.size()); //必须预先开辟足够空间
// transform(输入起始,输入结束,输出起始,处理函数)
transform(
nums.begin(), nums.end(),
squared.begin(),
[](int x){ return x*x; } //lambda匿名函数,每个元素求平方
);
for(auto x : squared) cout << x << " "; //输出1 4 9 16
return 0;
}
形式2:二元运算,两个输入序列
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> a = {1,2,3};
vector<int> b = {4,5,6};
vector<int> sum(a.size());
transform(
a.begin(), a.end(),
b.begin(),
sum.begin(),
[](int x, int y){return x+y;} //对应位置相加
);
for(auto s : sum) cout << s << " "; //5 7 9
return 0;
}
字符串大写转换示例
string s = "Hello world";
transform(s.begin(), s.end(), s.begin(), ::toupper);
//s变成 "HELLO WORLD"
第四部分 next_permutation 全排列(GESP5编程大题核心)
头文件
<algorithm>作用:生成字典序下一个更大的排列 规则:
- 如果存在下一个更大排列:修改数组,返回
true - 如果已经是最大排列:变回最小升序排列,返回
false⚠️必须先把数组排序成升序,do‑while循环,才能遍历全部排列!
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> pm = {1,2,3};
//一定要先排序!得到字典序最小排列
sort(pm.begin(), pm.end());
do{
//这里写对当前排列要做的业务逻辑
for(auto x:pm) cout << x << " ";
cout << endl;
}while(next_permutation(pm.begin(), pm.end()));
return 0;
}
时间复杂度:,题目条件一般,可以运行。
真题1:好斗的牛(PPT原题,完整注释)
题意:N头牛,枚举全部排列,求最少牛棚。 对于排列中第i头牛(i>=1),间隔 = max(前一头牛b值,当前牛a值);总牛棚 = n + 全部间隔之和。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n), b(n);
//读取每头牛的a[i]左边攻击范围
for(int i = 0; i < n; i++)
cin >> a[i];
//读取每头牛的b[i]右边攻击范围
for(int i = 0; i < n; i++)
cin >> b[i];
vector<int> pm(n);
for(int i = 0; i < n; i++)
pm[i] = i; //初始化排列:0,1,2...代表牛的编号
int ans = 1e9; //答案初始化为很大数字
do{
int cur_len = n; //每头牛占1个牛棚,基础长度n
//从第2头牛开始,计算和前一头之间需要留出多少牛棚
for(int i = 1; i < n; i++)
{
int prev_cow = pm[i-1]; //前一头牛编号
int now_cow = pm[i]; //当前牛编号
//间隔 = max(前一头牛的b,当前牛的a)
cur_len += max(b[prev_cow], a[now_cow]);
}
if(cur_len < ans)
ans = cur_len;
}while(next_permutation(pm.begin(), pm.end()));
cout << ans << endl;
return 0;
}
样例输入
2
1 2
1 2
输出 4
真题2:强化武器(选票模型,PPT完整注释)
题意:让1号武器材料数量严格大于其他所有武器,求最小花费。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_LEN = 1005;
int n, m;
int cnt[MAX_LEN]; // cnt[i]:武器i原始材料数量
vector<int> cost[MAX_LEN]; // cost[i]保存武器i所有修改花费
// aim:目标,希望1号武器最终有aim张选票
ll calc(int aim)
{
int cur_cnt = cnt[1]; //一号武器现有的选票
ll res = 0; //累计花费
vector<int> tmp; //收集剩余可以购买的选票花费
//遍历2~n号其他武器
for(int i = 2; i <= n; i++)
{
//需要买多少张,让该武器票数 <= aim‑1
int buy = max((int)cost[i].size() - aim + 1, 0);
//买最便宜的buy张
for(int j = 0; j < buy; j++)
{
res += cost[i][j];
cur_cnt++;
}
//剩下没有买的选票丢进tmp池子,后续可以花钱买来给一号
for(int j = buy; j < cost[i].size(); j++)
{
tmp.push_back(cost[i][j]);
}
}
sort(tmp.begin(), tmp.end()); //剩余池子从小到大排序
//一号还缺多少张,从池子买最便宜
for(int i = 0; i < aim - cur_cnt; i++)
{
res += tmp[i];
}
return res;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i++)
{
int p, c;
cin >> p >> c;
cnt[p]++;
cost[p].push_back(c);
}
//把每个武器的花费从小到大排序
for(int i = 1; i <= n; i++)
{
sort(cost[i].begin(), cost[i].end());
}
ll ans = 1e18;
//枚举一号武器最终aim张选票,aim范围:原始数量 ~ m
for(int i = max(cnt[1],1); i <= m; i++)
{
ans = min(ans, calc(i));
}
cout << ans << endl;
return 0;
}
样例输入
4 4
1 1
2 1
3 1
3 2
输出 1
课后作业题:健身房器械安排(N≤9,用next_permutation)
思路:N<=9,暴力枚举全部器械排列,对每种排列计算总空间,求最小值。 规则:相邻两台器械之间的间隔 = max(器械A的b,器械B的b,1),两台器械之间至少间隔1。 总长度 = 所有器械a宽度总和 + 全部相邻间隔总和。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n), b(n);
for(int i = 0; i < n; i++) cin >> a[i];
for(int i = 0; i < n; i++) cin >> b[i];
vector<int> pm(n);
for(int i = 0; i < n; i++) pm[i] = i;
int ans = 1e9;
do{
int total = 0;
//累加所有器械本身宽度
for(int i = 0; i < n; i++) total += a[pm[i]];
//累加相邻间隔
for(int i = 1; i < n; i++)
{
int pre = pm[i-1];
int now = pm[i];
int gap = max({b[pre], b[now], 1}); //至少间隔1
total += gap;
}
ans = min(ans, total);
}while(next_permutation(pm.begin(), pm.end()));
cout << ans << endl;
return 0;
}
样例输入1
2
2 3
0 0
输出:6
GESP5核心考点速记(考试复习)
- vector:连续内存,支持下标,头部插入慢;list双向链表,不支持下标,中间插入快。
- list排序用
.sort()成员函数,不能用sort();vector用sort(v.begin(),v.end())。 next_permutation求全排列,必须先sort升序,搭配do‑while。- transform批量处理容器元素,支持一元、二元lambda。
- N<=9,总排列数,可以暴力枚举全部排列。
2 条评论
-
admin SU @ 2026-9-4 19:40:17
C++序列容器零基础教程(GESP5)
本教程基于PPT《序列容器类》编写,面向零基础,大量注释,通俗讲解,包含
vector、list、迭代器、STL算法、真题实战。 头文件总览:#include <vector>动态数组容器#include <list>双向链表容器#include <algorithm>STL算法库 sort、reverse、transform、next_permutation#include <iostream>输入输出
一、什么是容器?
容器就是C++标准库帮我们写好的“装数据的盒子”。 普通数组缺点:大小固定,不能动态增加元素。 容器可以自动扩容,自带增删改查一堆现成函数。 两类重点序列容器:
vector:动态数组,内存连续,随机访问快,中间插入删除慢list:双向链表,内存不连续,任意位置插入删除快,随机访问慢
特性 vector list 底层 动态数组 双向链表 随机访问 vec[0]✅ O(1) ❌ 只能迭代器 O(n) 尾部增删 很快 O(1) 很快 O(1) 头部/中间插入删除 慢 O(n) 排序 用 sort()算法成员函数 .sort(),不能用algorithm的sort
二、vector 动态数组(最常用)
头文件:
#include <vector>2.1 vector创建的4种写法
#include <iostream> #include <vector> using namespace std; int main() { //写法1:空vector,size=0,后面可以push_back加元素 vector<int> v1; //写法2:创建5个int,全部初始化为0 vector<int> v2(5); //写法3:创建5个int,全部初始化为42 vector<int> v3(5, 42); //写法4:C++11直接初始化列表 vector<int> v4 = {10,20,30,40}; return 0; }2.2 vector常用成员方法
函数 作用 .size()返回元素个数 O(1) .empty()判断是否为空 true空 false不为空 .push_back(x)尾部追加元素x .pop_back()删除尾部元素 .clear()清空全部元素 .front()取第一个元素 .back()取最后一个元素 .resize(n)修改容器大小 .begin()迭代器:指向第一个元素 .end()迭代器:指向最后元素的下一个位置 2.3 vector访问元素三种方式
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v = {10,20,30,40}; //方式1:下标 [] 和普通数组一样,下标从0开始 cout << v[0] << endl; //方式2:at(),越界会报错,[]越界不会报错,建议调试用at cout << v.at(1) << endl; //方式3:迭代器,类似指针 vector<int>::iterator it = v.begin(); cout << *it << endl; //*解引用,拿到迭代器指向的值 return 0; }2.4 vector遍历三种写法
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v = {1,2,3,4,5}; //方式1:范围for循环(最简单,C++11) cout << "范围for:"; for(auto num : v){ cout << num << " "; } cout << endl; //方式2:下标for循环,和数组一样 cout << "下标循环:"; for(int i = 0; i < v.size(); i++){ cout << v[i] << " "; } cout << endl; //方式3:迭代器循环,记住条件 it != v.end(),不要用 < cout << "迭代器循环:"; for(vector<int>::iterator it = v.begin(); it != v.end(); it++){ cout << *it << " "; } cout << endl; return 0; }2.5 vector插入删除
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v = {10,30,40}; //insert(迭代器位置,值):在迭代器前面插入元素 v.insert(v.begin()+1, 20); //在10和30中间插入20 → {10,20,30,40} //erase(迭代器位置) 删除该位置元素 v.erase(v.begin()+2); //删掉30 for(auto x:v) cout << x << " "; return 0; }
三、list双向链表容器
头文件:
#include <list>list不支持下标
lst[0]!不能随机访问!只能迭代器遍历。3.1 list常用方法
函数 作用 .push_back(x)尾部加 .push_front(x)头部插入,vector没有这个函数 .pop_back()尾部删 .pop_front()头部删 .empty()判空 .size()返回元素数量,O(n) .front()头元素 .back()尾元素 .clear()清空 .insert(pos,val)pos迭代器前插入val .erase(pos)删除pos迭代器元素 .sort()list自己的排序成员函数,不要用algorithm::sort 3.2 list遍历示例
#include <iostream> #include <list> using namespace std; int main() { list<int> lst; lst.push_back(10); lst.push_back(20); lst.push_front(5); //头部插入5 → {5,10,20} //1.范围for for(auto e : lst){ cout << e << " "; } cout << endl; //2.正向迭代器 for(auto it = lst.begin(); it != lst.end(); it++){ cout << *it << " "; } cout << endl; //3.反向迭代器 rbegin rend,倒序遍历 for(auto it = lst.rbegin(); it != lst.rend(); it++){ cout << *it << " "; } cout << endl; //list专属排序,不能写 sort(lst.begin(),lst.end())! lst.sort(); return 0; }⚠️重点坑:
sort( begin,end )是algorithm库函数,不能给list用。list只能调用自己成员函数lst.sort()
四、STL通用算法(algorithm头文件)
4.1 sort、reverse
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> v = {3,1,4,2}; //sort(起始迭代器,结束迭代器) 默认升序 sort(v.begin(), v.end()); //1 2 3 4 //reverse反转区间 reverse(v.begin(), v.end()); //4 3 2 1 for(auto x:v) cout << x << " "; return 0; }4.2 next_permutation 生成全排列⭐GESP高频
字典序排列,
next_permutation(begin,end)功能:生成下一个字典序更大排列 返回true:成功得到下一个排列;返回false:已经最大排列,重置为最小升序。 ✅使用前提:初始数组必须是升序! 才能遍历全部排列。#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> pm = {1,2,3}; //初始必须升序!do while循环遍历全部排列 do{ for(auto x:pm){ cout << x << " "; } cout << endl; }while(next_permutation(pm.begin(), pm.end())); return 0; }输出所有6种排列。
N<=9的时候 9! =362880,计算机可以轻松跑完。PPT中“好斗的牛”就是依靠这个枚举全部排列求最优解。
4.3 transform 转换容器元素
transform:批量处理容器数据,可以单参数、双参数。需要预先开辟输出空间。#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> nums = {1,2,3,4}; vector<int> square(nums.size()); //提前准备空间 //单参数transform:每个元素求平方 transform( nums.begin(), nums.end(), //输入范围 square.begin(), //输出起始位置 [](int x){return x*x;} //lambda匿名函数,输入x返回x*x ); for(auto x : square) cout << x << " "; cout << endl; //双参数transform:两个vector对应相加 vector<int> a={1,2,3}, b={10,20,30}; vector<int> sum(3); transform( a.begin(),a.end(), b.begin(), sum.begin(), [](int x,int y){return x+y;} ); for(auto x:sum) cout << x << " "; return 0; }[](int x){return x*x;}叫做lambda匿名函数,临时写一个小函数给算法使用。
五、真题实战1:好斗的牛(next_permutation全排列)
题目简述:N头牛,每头牛左边
a[i]不能有牛,右边b[i]不能有牛。求安排顺序后最少牛棚数量。 规则:相邻两头牛X、Y,中间间隔 =max(X.b , Y.a);总长度 = N头牛本身占N格 + 所有间隔。N≤9,枚举全部排列求最小值。
#include <iostream> #include <algorithm> #include <vector> using namespace std; int main() { int n; cin >> n; vector<int> a(n), b(n); //读入a数组:每头牛左边警戒数量 for(int i = 0; i < n; i++){ cin >> a[i]; } //读入b数组:每头牛右边警戒数量 for(int i = 0; i < n; i++){ cin >> b[i]; } vector<int> pm(n); for(int i = 0; i < n; i++){ pm[i] = i; //初始排列0,1,2...n-1,代表牛编号 } int ans = 1e9; //答案初始无穷大 do{ int cur_len = n; //n头牛,自身占n个牛棚 for(int i = 1; i < n; i++){ int prev_cow = pm[i-1]; //前一头牛 int now_cow = pm[i]; //当前牛 //中间间隔 = max(前一头牛的b,当前牛的a) cur_len += max(b[prev_cow], a[now_cow]); } if(cur_len < ans){ ans = cur_len; } }while(next_permutation(pm.begin(), pm.end())); cout << ans << endl; return 0; }输入样例
2 1 2 1 2输出
4,与PPT样例一致。
六、真题实战2:强化武器(选票模型)
题意:m张选票,希望1号武器票数严格大于所有其他武器,求最小花费。 思路:枚举目标票数
aim(1号武器想要拿到aim张);- 其他人票数最多只能
aim‑1;超过的选票要买走,优先买便宜; - 买完强制削减的选票后,如果1号票数还不足aim,再从剩下选票挑最便宜补齐。
#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1005; int n,m; int cnt[MAXN]; //cnt[i]:武器i原始选票数量 vector<int> cost[MAXN]; //cost[i]保存武器i所有选票花费 //calc函数:计算当1号目标aim张选票,需要多少金币 ll calc(int aim) { int cur = cnt[1]; //一号武器现在手里票数 ll res = 0; //总花费 vector<int> rest; //存放所有剩下可以买的选票花费 for(int i = 2; i <= n; i++) { //这个候选人需要强制买走多少张,保证不超过aim‑1 int need_buy = max((int)cost[i].size() - (aim-1), 0); for(int j = 0; j < need_buy; j++) { res += cost[i][j]; //买最便宜need_buy张 cur++; //一号武器票数增加 } //剩下选票放进候选池子,以后缺票可以从这里买 for(int j = need_buy; j < cost[i].size(); j++) { rest.push_back(cost[i][j]); } } sort(rest.begin(), rest.end()); //池子从小到大排序 //还缺多少票 for(int i = 0; i < aim - cur; i++) { res += rest[i]; } return res; } int main() { cin >> n >> m; for(int i = 1; i <= m; i++) { int p,c; cin >> p >> c; cnt[p]++; cost[p].push_back(c); } //每个武器内部选票花费从小到大排序 for(int i = 1; i <= n; i++) { sort(cost[i].begin(), cost[i].end()); } ll ans = 1e18; //枚举所有可能aim:最少是原本一号票数,最多m张 for(int aim = cnt[1]; aim <= m; aim++) { ans = min(ans, calc(aim)); } cout << ans << endl; return 0; }样例输入
4 4 1 1 2 1 3 1 3 2输出
1。
七、课后作业:健身房器械安排(作业题)
N≤9,用next_permutation枚举全部排列。 每台器械宽度
a[i];左右最小间隔b[i];两台器械中间间隔 =max(左边器械b[i],右边器械b[j],1),最小间隔强制为1。总长度=所有器械宽度之和 + 所有相邻间隔。求全局最小总长度。#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<int> a(n), b(n); for(int i=0;i<n;i++) cin >> a[i]; for(int i=0;i<n;i++) cin >> b[i]; vector<int> pm(n); for(int i=0;i<n;i++) pm[i]=i; int ans = 1e9; do{ int total_width = 0; //累加所有器械自身宽度 for(int i=0;i<n;i++) total_width += a[pm[i]]; //计算相邻间隔 for(int i=1;i<n;i++){ int left = pm[i-1]; int right = pm[i]; //间隔取 max(左边b,右边b,1) int gap = max(max(b[left], b[right]), 1); total_width += gap; } ans = min(ans, total_width); }while(next_permutation(pm.begin(), pm.end())); cout << ans << endl; return 0; }样例输入1
2 2 3 0 0输出:
6
八、重点易错总结(考试必背)
vector内存连续,支持下标;list链表,不支持下标访问。- list排序必须写
.sort()成员函数,不能sort(lst.begin(),lst.end())。 next_permutation做全排列,初始数组必须升序,搭配do while。- 迭代器循环判断条件:
it != end(),不要写it < end()(list迭代器不支持小于比较)。 front()、back()调用前容器不能为空,否则程序崩溃。- transform输出容器需要提前开辟足够size空间,不能直接空vector。
- N<=9,
9! =362880,暴力枚举全部排列时间完全可以接受。
-
@ 2026-9-4 19:31:54
C++ vector / list 容器函数对照表(0基础版)
头文件
- vector:
#include <vector> - list:
#include <list> - 通用算法(sort、reverse、next_permutation、transform):
#include <algorithm>
名词解释
- 迭代器 iterator:类似“指向容器元素的指针”,
begin()开头,end()末尾下一位;*迭代器取出元素。 - ✅支持;❌不支持;⚠️注意坑点
一、成员函数对比表(容器自己自带的函数)
函数/方法 功能说明 vector(动态数组) list(双向链表) .size()返回容器内元素个数 ✅ O(1) ✅ ⚠️PPT写O(n)(老标准) .empty()判断容器是否为空,空返回true ✅ ✅ .clear()清空容器全部元素,size变成0 .front()获取第一个元素的引用(容器不能为空!) .back()获取最后一个元素的引用(容器不能为空!) .push_back(val)尾部添加元素val .pop_back()删除尾部元素 .push_front(val)头部添加元素val ❌没有这个函数 .pop_front()删除头部元素 .begin()返回指向第一个元素的迭代器 ✅ .end()返回最后元素下一个位置迭代器 .rbegin()反向迭代器:指向最后一个元素 .rend()反向迭代器:指向第一个元素前面 .insert(pos, val)在迭代器 pos前面插入val,返回新元素迭代器✅ O(n) 中间插入慢 ✅ O(1) 任意位置插入快 .erase(pos)删除迭代器pos指向的元素,返回后一个元素迭代器 ✅ O(n) ✅ O(1) .sort()容器自带排序成员函数 ❌没有! ✅ lst.sort()默认升序[下标]数组下标访问,例如 v[2]✅ O(1)随机访问 ❌完全不支持下标!不能写lst[0] .at(下标)下标访问,越界会报错 ✅ ❌不支持 ⚠️超级重要坑:
- list 不能用下标
lst[i]!访问元素只能靠迭代器 / 范围for循环。 - vector没有
push_front,想在头部加元素只能用insert(vec.begin(), val),速度很慢O(n)。 - list不要用全局
sort()算法!要用自己的成员函数.sort()。
二、
<algorithm>通用算法函数(不属于容器,全局函数)这些函数不是vector/list自带,要传入**迭代器区间
begin, end**使用函数 作用 可以用于vector 可以用于list sort(begin, end)对区间升序排序 ✅ ❌ list不能用!用 .sort()reverse(begin, end)反转区间元素顺序 ✅ next_permutation(begin,end)生成字典序下一个排列 ❌不支持 transform(in_begin,in_end,out_begin, op)批量处理每个元素 ✅ 简单示例
vector<int> v={3,1,2}; sort(v.begin(),v.end()); //正确 list<int> lst={3,1,2}; // sort(lst.begin(),lst.end()); //错误! lst.sort(); //正确,调用list自己的排序
三、遍历写法对比(0基础必背)
1)vector三种遍历
vector<int> v={1,2,3,4}; //①下标遍历(只有vector能用!list不行) for(int i=0;i<v.size();i++){ cout << v[i]; } //②范围for循环,vector、list通用 for(auto x : v){ cout << x; } //③迭代器遍历,vector、list通用 for(auto it = v.begin(); it != v.end(); it++){ cout << *it; //*it取出迭代器对应元素 }2)list两种遍历(❌不能下标)
list<int> lst={1,2,3,4}; //①范围for循环 for(auto x : lst){ cout << x; } //②迭代器遍历 for(auto it = lst.begin(); it != lst.end(); it++){ cout << *it; } //倒序遍历,反向迭代器 for(auto it = lst.rbegin(); it != lst.rend(); it++){ cout << *it; }
四、时间复杂度速查表(GESP选择题高频)
操作 vector list 随机访问(取第k个元素) ,必须一步步移动迭代器 尾部增加/删除 push_back / pop_back 分摊 头部增加/删除 ,大量元素移动 中间位置插入/删除 (前提已经拿到迭代器) 什么时候选vector? 大部分场景,需要随机下标访问、主要只在尾部增删。
什么时候选list? 需要频繁在头部、中间插入删除元素;不需要随机下标访问。
五、常见易错代码对比(考试坑)
错误代码 正确代码 原因 list<int> lst; cout << lst[0];使用迭代器 *lst.begin()list不支持下标[] sort(lst.begin(),lst.end());lst.sort();list不能用algorithm库sort vector<int> v; v.push_front(5);v.insert(v.begin(),5);vector没有push_front transform(a.begin(),a.end(),b.begin(),func);预先保证b容器有足够size空间 transform不会自动扩容 next_permutation(v.begin(),v.end());前没有sort先 sort(v.begin(),v.end());再do‑whilenext_permutation要从最小排列开始才能遍历全部排列
六、极简记忆口诀
- vector是动态数组,内存连续,可以下标,头插慢;
- list双向链表,不能下标,任意位置插入删除快;
- vector用sort全局函数,list用自己的.sort();
- next_permutation只支持vector数组,搭配do‑while全排列。
- vector:
- 1