C++入门指南
C++ STL 全面入门指南
STL 是 C++ 中强大且广泛使用的一部分,包含许多 常用数据结构 和 算法工具,可以大大简化开发过程。
STL 大致分为三大部分:
- 容器 Containers:数据结构
- 算法 Algorithms:排序、查找、修改等
- 迭代器 Iterators:容器和算法之间的桥梁
容器 Containers
容器就是用来“装”数据的,我们常用的有两大类:
顺序容器(元素按插入顺序存储):
| 容器 | 特点 |
|---|---|
vector |
动态数组,支持随机访问,常用 |
deque |
双端队列,支持头尾插入删除 |
list |
双向链表,插入/删除效率高,不支持随机访问 |
array |
固定大小的数组(C++11 引入) |
forward_list |
单向链表(C++11 引入) |
关联容器(基于平衡二叉树,元素自动排序):
| 容器 | 特点 |
|---|---|
set |
元素唯一,自动排序 |
multiset |
元素可重复,自动排序 |
map |
键值对(key-value),key 唯一 |
multimap |
键值对,key 可重复 |
无序关联容器(基于哈希表,查找快):
| 容器 | 特点 |
|---|---|
unordered_set |
元素唯一,哈希结构 |
unordered_map |
键值对,key 唯一,哈希结构 |
unordered_multiset / unordered_multimap |
对应支持重复元素 |
动态数组 vector
常用操作:
| 操作 | 说明 | 示例 |
|---|---|---|
| 定义 | 空:vector<int> v; 初始值:vector<int> v(5, 0); |
长度5,全部是0 |
| 添加元素 | push_back(x) |
尾部加元素 |
| 删除元素 | pop_back() |
删除最后一个元素 |
| 获取大小 | size() |
返回当前元素个数 |
| 下标访问 | v[i] 或 at(i) |
at(i) 有边界检查 |
| 清空 | clear() |
全部删掉 |
| 插入 | insert(it, val) |
在指定位置插入 |
| 删除 | erase(it) / erase(beg, end) |
删除一个或一段元素 |
| 排序 | sort(v.begin(), v.end()) |
从小到大排序 |
| 反转 | reverse(v.begin(), v.end()) |
翻转整个 vector |
| 查找 | find(v.begin(), v.end(), x) |
需要 #include <algorithm> |
示例代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> vec(10,0); //指定长度为10,默认值为0的vector // 0000000000
for(int num:vec){ //遍历
cout << num;
}
cout << endl;
vec.push_back(2); //尾接 // 00000000002
vec.pop_back(); //尾删除 // 0000000000
vector<vector<int>> mat(100,vector<int>(100,0)); //构造二维vector
cout << "vec的长度:" << vec.size() << endl; //vec的长度:10
vec.clear(); //清空vector
cout << "vec的长度:" << vec.size() << endl; //vec的长度:0
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
cout << "尾部元素" << vec.back() << endl;
return 0;
}
栈 stack
“栈”的抽象数据结构定义 —— 后进先出(LIFO)。
#include <bits/stdc++.h>
using namespace std;
int main(){
stack<int> stk;
stk.push(1); //入栈
stk.push(2);
stk.push(3);
stk.push(4);
int top = stk.top(); //取栈顶
cout << "top: "<< top<< endl; //打印
stk.pop(); //出栈
top = stk.top(); //取栈顶
cout << "top: "<< top<< endl; //打印
return 0;
}
队列 queue
“队列”的抽象数据结构定义 —— 先进先出(FIFO)。
常用方法:
| 作用 | 用法 | 示例 |
|---|---|---|
| 构造 | queue<类型> que |
queue<int> que; |
| 进队 | .push(元素) |
que.push(1); |
| 出队 | .pop() |
que.pop(); |
| 取队首 | .front() |
int a = que.front(); |
| 取队尾 | .back() |
int a = que.back(); |
| 查看大小 / 清空 / 判空 | 略 | 略 |
#include <bits/stdc++.h>
using namespace std;
int main(){
queue<int> que;
que.push(1);
que.push(2);
que.push(3);
cout << "队首" << que.front() << endl; //队首1
cout << "队尾" << que.back() << endl; //队尾3
que.pop(); //出队,队头元素1出队
cout << "队尾" << que.front() << endl; //队首2
return 0;
}
优先队列 priority_queue
优先队列和普通队列不同,普通队列是先进先出(FIFO),但优先队列每次取出的都是“最大(或最小)”的元素,按照优先级排序。
常用方法:
| 方法 | 说明 |
|---|---|
push(x) |
插入元素 x |
pop() |
删除优先级最高的元素 |
top() |
返回优先级最高的元素 |
empty() |
判断是否为空 |
size() |
返回元素个数 |
堆是一种非线性结构,可以把堆看作一棵二叉树,也可以看作一个数组,即:堆就是利用完全二叉树的结构来维护的一维数组。
堆可以分为大顶堆和小顶堆。
- 大顶堆:每个结点的值都大于或等于其左右孩子结点的值。
- 小顶堆:每个结点的值都小于或等于其左右孩子结点的值。
默认用法:大顶堆
#include <bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int> pq;
pq.push(5); //插入元素
pq.push(1);
pq.push(10);
cout << "top: " << pq.top() << endl; //输出最大元素 10
pq.pop(); //弹出最大元素
cout << "top: " << pq.top() << endl; //输出最大元素 5
return 0;
}
自定义用法:小顶堆
#include <bits/stdc++.h>
using namespace std;
int main(){
priority_queue<int,vector<int>,greater<int>> pq; //小顶堆
pq.push(5);
pq.push(1);
pq.push(10);
cout << pq.top() << endl; // 输出最小元素:1
pq.pop();
cout << pq.top() << endl; // 现在最小是:5
return 0;
}
集合 set
定义:set是一个不允许元素重复的有序容器,底层使用的是红黑树来实现的,自动保持元素的有序性。
基本特性:
| 特性 | 描述 |
|---|---|
| 元素唯一 | 自动去重(底层基于红黑树) |
| 有序排列 | 元素总是从小到大排序(默认) |
| 支持快速查找 | 时间复杂度 O(log n) |
| 插入删除快 | 时间复杂度 O(log n) |
| 不支持下标访问 | 因为它是基于树,不是数组 |
常用方法:
| 方法 | 说明 |
|---|---|
s.insert(x) |
插入元素,自动排序、去重 |
s.find(x) |
返回迭代器,如果找不到是 s.end()`` |
s.erase(x) |
删除值为 x 的元素 |
empty() |
判断是否为空 |
for (int x : s) |
从小到大 |
s.size() |
元素个数 |
示例代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
set<int> s;
//插入元素
s.insert(5);
s.insert(2);
s.insert(5); //重复插入,不会生效
//遍历输出
for(int x : s){
cout << x << " ";
}
cout << endl; // 输出:2 5
//查找元素
if(s.find(2) != s.end()){
cout << "找到了元素2" << endl;
}
//删除元素
s.erase(2);
s.erase(s.begin()); //删除第一个元素
//判断是否为空
if(s.empty()) cout << "集合为空" << endl;
return 0;
}
三种集合的区别:
| 集合三要素 | 解释 | set | multiset | unordered_set |
|---|---|---|---|---|
| 确定性 | 一个元素要么在集合中,要么不在 | ✔ | ✔ | ✔ |
| 互异性 | 一个元素仅可以在集合中出现一次 | ✔ | ❌(任意次) | ✔ |
| 无序性 | 集合中的元素是没有顺序的 | ❌(从小到大) | ❌(从小到大) | ✔ |
映射 map
map是一种关联容器,他存储的是键值对,并且key是唯一的,自动按顺序排序。
常用方法:
| 操作 | 用法 | 说明 |
|---|---|---|
| 插入 | m[key] = value 或 insert({key, value}) |
有则改,无则加 |
| 访问值 | m[key] |
直接访问,若 key 不存在会自动创建并赋默认值 |
| 查找 | m.find(key) |
返回迭代器 |
| 删除 | m.erase(key) 或 m.erase(it) |
根据 key 或迭代器删 |
| 遍历 | for (auto p : m) |
从小到大按 key 遍历 |
| 大小 | m.size() |
元素对数 |
| 清空 | m.clear() |
清空整个 map |
示例代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
map<string,int> score;
// 插入元素,两种方式
score["Alice"] = 90;
score.insert({"Bob",85});
//修改值
score["Bob"] = 88;
//访问元素
cout << "Alice: " << score["Alice"] << endl;
//遍历map
for(auto p : score){
cout << p.first << " 分数是 " << p.second << endl;
}
//查找key是否存在
if (score.find("Charlie") == score.end()) {
cout << "Charlie 不存在" << endl;
}
return 0;
}
三种map的区别:
| 容器 | 是否排序 | 是否去重 | 底层结构 | 查找效率 |
|---|---|---|---|---|
map |
✅ 有序 | ✅ key 唯一 | 红黑树 | O(log n) |
unordered_map |
❌ 无序 | ✅ key 唯一 | 哈希表 | O(1) 平均 |
multimap |
✅ 有序 | ❌ key 可重复 | 红黑树 | O(log n) |
map统计单词频率的案例
#include <bits/stdc++.h>
using namespace std;
int main(){
map<string,int> wordCount;
string word;
cout << "Enter words (Ctrl+D/Ctrl+Z to end):" << endl;
while(cin>>word){
wordCount[word]++;
}
for(const auto& pair : wordCount){
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
字符串 string
在 C++ 中,string 是一个 标准库中的类(属于
| 操作 | 示例 | 说明 |
|---|---|---|
| 创建字符串 | string s = "abc"; |
初始化字符串 |
| 拼接 | s1 + s2 |
合并字符串 |
| 获取长度 | s.size() 或 s.length() |
返回字符串长度 |
| 访问字符 | s[i] |
类似数组,访问第 i 个字符 |
| 添加字符 | s.push_back('x') |
在末尾加一个字符 |
| 删除字符 | s.pop_back() |
删除最后一个字符 |
| 截取字符串 | s.substr(pos, len) |
从 pos 开始截取 len 个字符 |
| 查找字符串 | s.find("abc") |
返回子串起始下标,找不到返回 string::npos |
| 替换 | s.replace(pos, len, "new") |
替换部分内容 |
| 清空 | s.clear() |
清空字符串 |
| 判断是否为空 | s.empty() |
判断字符串是否为空 |
示例代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
string s1; //构造字符串,为空
string s2 = "qwe"; //构造字符串,并赋值qwe
string s3(10,'6'); // 构造字符串,通过构造函数构造为6666666666
cout << s3 << endl;
string s = "HelloWorld";
// 取前5个字符
string sub = s.substr(0, 5); // Hello
// 查找字符
int pos = s.find("World"); // pos = 5
// 替换字符
s.replace(5, 5, "CPP"); // HelloCPP
cout << s << endl; // HelloCPP
return 0;
}
二元组 pair
pair 是一个模板类,用来将两个值打包成一个组合,就像一对搭档一样
示例代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
pair<string,int> p = {"Apple",1};
cout << p.first << ", " << p.second << endl; //Apple, 1
return 0;
}
📦常用方法:
| 操作 | 说明 | 示例 |
|---|---|---|
| 创建 | 定义一个 pair | pair<int, string> p(1, "hi"); |
| 快速构造 | 使用 make_pair |
auto p = make_pair(2, "hello"); |
| 访问元素 | 用 .first 和 .second |
p.first, p.second |
| 赋值/比较 | 可以用 ==, < 等运算符 |
p1 < p2 按 first 比,若相等再比 second |
算法 Algorithms
STL 提供了超过 60 种常用算法,常用的有:
- 排序:
sort(),stable_sort() - 查找:
find(),binary_search() - 统计:
count(),accumulate() - 修改:
reverse(),rotate(),remove()
比如对一个 vector 排序:
#include <algorithm>
#include <vector>
std::vector<int> v = {5, 3, 1, 4, 2};
std::sort(v.begin(), v.end()); // 升序排序
二分查找函数
🔍 简单一句话:
| 函数名 | 功能 |
|---|---|
lower_bound() |
返回第一个 ≥ 某个值的位置 |
upper_bound() |
返回第一个 > 某个值的位置 |
📈 举个例子:
对于数组:[1, 2, 4, 4, 4, 7, 9]
| 查找值 | lower_bound 位置 |
upper_bound 位置 |
|---|---|---|
| 4 | 第一个 ≥ 4 的位置 = 下标 2 | 第一个 > 4 的位置 = 下标 5 |
| 3 | 下标 2 | 下标 2 |
| 10 | 下标 7(末尾) | 下标 7 |
统计某个数字出现次数的示例:
#include <iostream>
#include <vector>
#include <algorithm> // 引入 lower_bound 和 upper_bound
using namespace std;
int main() {
vector<int> v = {1, 2, 4, 4, 4, 7, 9};
int x = 4;
int count = upper_bound(v.begin(), v.end(), x) - lower_bound(v.begin(), v.end(), x);
cout << x << " 出现了 " << count << " 次。" << endl;
return 0;
}
next_permutation
C++STL中的全排列函数为两个:next_permutation和prev_permutation,其中:next_permutation实现升序,而prev_permutation实现降序
next_permutation 需要初始数组是字典序最小的排列,才能生成所有字典序的全排列。如果数组的初始排列不是字典序最小的,某些排列可能会被跳过。
使用示例:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3};
do {
for (int num : nums) cout << num << " ";
cout << endl;
} while (next_permutation(nums.begin(), nums.end()));
return 0;
}
输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
迭代器 Iterators
迭代器是 STL 的灵魂,像指针一样访问容器中的元素。
常见类型有:
begin():指向容器起始位置end():指向容器最后一个元素的下一个位置rbegin()/rend():反向迭代器cbegin()/cend():常量迭代器(不可修改值)
一个简单的例子:
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> vec = {1,2,3,4,5};
// 定义一个迭代器
vector<int>::iterator it;
for(it = vec.begin();it!=vec.end();it++){
cout << *it << " "; //解引用访问值
}
// 1 2 3 4 5
return 0;
}
💡 从 C++11 开始你可以偷懒写:
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> vec = {1,2,3,4,5};
for(auto it = vec.begin();it!=vec.end();it++){
cout << *it << " "; //解引用访问值
}
// 1 2 3 4 5
return 0;
}

浙公网安备 33010602011771号