算法刷题中,C++ 凭借高效的执行效率、丰富的标准库(STL)成为主流选择。本教程聚焦刷题高频语法,摒弃冗余知识点,直击核心应用,帮助你快速掌握算法刷题所需的 C++ 语法工具。
1. 关于std
std是C++ 标准库的命名空间,全称是 “standard(标准)”。
C++ 把标准库(比如vector、cout、string等)里的所有工具都放在std这个命名空间下,目的是避免不同代码的同名冲突(比如你自己写的vector和标准库的vector不会混淆)。
标准库的所有核心功能都隶属于std,常见示例:
- 输入输出相关:
std::cout(标准输出)、std::cin(标准输入)、std::cerr(标准错误输出) - 字符串类:
std::string - 容器类:
std::vector(动态数组)、std::map(键值对映射)、std::list(双向链表) - 算法相关:
std::sort(排序)、std::find(查找) - 其他:
std::endl(换行并刷新缓冲区)、std::pair(键值对)、std::unique_ptr(智能指针)
2. 关于::
::是作用域解析运算符,用来明确指定 “某个名字属于哪个作用域”。
常见用法有两种:
- 当用
std::vector时,::表示 “vector是std这个命名空间里的工具”; - 也可以用于类的成员(比如
ClassA::func()表示func是ClassA类里的成员函数)。
简单说:std是标准库的 “容器”,::是 “钥匙”,用来从这个容器里取出你需要的工具~
一、基础语法(与 C 语言兼容 + 刷题必备扩展)
1. 头文件与命名空间
using namespace std;
---> 简化代码,避免重复写std::(刷题场景下推荐使用,工程开发需谨慎)
// 刷题核心头文件(包含绝大多数常用功能,无需单独引入stdio.h等) #include <iostream> #include <vector> #include <string> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> // 简化代码,避免重复写std::(刷题场景下推荐使用,工程开发需谨慎) using namespace std;2. 输入输出(高效适配刷题场景)
(1)基础输入输出
// 替代C语言的printf/scanf,语法更简洁 int a; string s; cin >> a >> s; // 自动忽略空格、换行符 cout << "结果:" << a << " " << s << endl; // endl 等价于换行+刷新缓冲区(2)高效输入输出(应对大数据量)
当题目输入数据量较大时,cin/cout速度可能不足,需关闭同步加速:
#include <iostream> using namespace std; int main() { // 关闭cin与stdio的同步,加速输入输出 ios::sync_with_stdio(false); cin.tie(nullptr); // 解除cin与cout的绑定,进一步提速 int n; cin >> n; for (int i = 0; i < n; i++) { int x; cin >> x; cout << x << " "; } return 0; }(3)多行字符串 / 带空格输入
string str; getline(cin, str); // 读取一整行(包含空格),注意前面若有cin需先处理换行符3. 变量与数据类型
(1)基本数据类型
| 类型 | 用途 | 示例 |
|---|---|---|
int | 整数(常规算法场景) | int x = 10; |
long long | 大数场景(防止溢出) | long long sum = 0LL; |
double | 浮点数(精度要求不高) | double pi = 3.14159; |
bool | 布尔值(判断条件) | bool flag = true; |
char | 单个字符 | char c = 'a'; |
string | 字符串(高频使用) | string s = "algorithm"; |
(2)常量定义
// 两种方式:#define 或 const #define MAXN 100005 // 无类型,简单直接,刷题常用 const int MOD = 1e9 + 7; // 有类型,编译期检查,推荐用于常量值4. 循环与条件判断
(1)循环结构(刷题高频)
// 1. for循环(最常用,适合已知循环次数) for (int i = 0; i < 10; i++) { cout << i << " "; } // 2. while循环(适合未知循环次数) int x = 0; while (x < 10) { x++; } // 3. do-while循环(至少执行一次,刷题较少用) int y = 0; do { y++; } while (y < 10); // 4. 范围for循环(C++11及以上,遍历容器便捷) vector<int> vec = {1,2,3,4}; for (int num : vec) { cout << num << " "; }(2)条件判断
// 1. if-else int a = 5; if (a > 10) { cout << "大于10"; } else if (a > 5) { cout << "大于5小于等于10"; } else { cout << "小于等于5"; } // 2. switch(适合多分支判断,刷题较少用) int b = 2; switch (b) { case 1: cout << "一"; break; case 2: cout << "二"; break; default: cout << "其他"; }5. 函数与指针(简化版,刷题聚焦实用)
(1)普通函数(算法封装)
// 函数定义:返回值类型 函数名(参数列表) int add(int a, int b) { return a + b; } // 函数调用 int res = add(3, 5);(2)Lambda 表达式(C++11 及以上,刷题高频,简化临时函数)
常用于排序、遍历等场景,无需单独定义函数:
#include <vector> #include <algorithm> int main() { vector<int> vec = {3,1,4,2}; // Lambda表达式作为排序规则(降序排序) sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); return 0; }(3)指针简化使用
刷题中指针多与数组、容器配合,无需复杂操作:
int arr[] = {1,2,3}; int *p = arr; // 数组名等价于首元素指针 cout << *p << endl; // 输出1(解引用) cout << *(p+1) << endl; // 输出2(指针偏移)二、核心容器(STL)—— 算法刷题的灵魂
STL 容器提供了高效的数据结构实现,避免手动编写底层代码,大幅提升刷题效率。
1. 向量(vector)—— 动态数组(最常用)
(1)基本用法
#include <vector> int main() { // 初始化方式 vector<int> vec1; // 空向量 vector<int> vec2(5, 0); // 5个元素,每个初始化为0 vector<int> vec3 = {1,2,3,4,5}; // 直接初始化 vector<int> vec4(vec3); // 拷贝初始化 // 核心操作 vec1.push_back(6); // 尾部添加元素(O(1),均摊复杂度) vec1.pop_back(); // 尾部删除元素(O(1)) vec1.size(); // 获取元素个数(O(1)) vec1.empty(); // 判断是否为空(O(1)) vec1.clear(); // 清空所有元素(O(n)) vec1[0]; // 访问第0个元素(O(1),不做越界检查) vec1.at(0); // 访问第0个元素(O(1),越界抛异常,刷题少用) vec1.begin(); // 返回首元素迭代器 vec1.end(); // 返回尾后迭代器(不指向任何元素) // 遍历方式 for (int i = 0; i < vec3.size(); i++) { cout << vec3[i] << " "; } return 0; }(2)刷题常用场景
- 存储动态变化的数据集(如输入未知长度的数组)
- 作为临时数组、结果容器
- 替代普通数组,无需担心越界(灵活扩容)
2. 字符串(string)—— 字符序列
#include <string> int main() { string s1 = "hello"; string s2("world"); string s3 = s1 + " " + s2; // 字符串拼接(便捷) // 核心操作 s1.length(); // 字符串长度(等价于size()) s1.empty(); // 判断是否为空 s1.clear(); // 清空字符串 s1[0] = 'H'; // 修改单个字符 s1.append("!"); // 尾部追加字符串 s1.substr(1, 3); // 截取子串:从索引1开始,长度3 s1.find("ll"); // 查找子串,返回首次出现的索引,未找到返回string::npos s1.erase(1, 2); // 删除从索引1开始的2个字符 // 遍历 for (char c : s1) { cout << c; } return 0; }3. 栈(stack)—— 先进后出(LIFO)
#include <stack> int main() { stack<int> st; // 核心操作 st.push(10); // 入栈(顶部添加) st.push(20); st.top(); // 获取栈顶元素(不删除,O(1)) st.pop(); // 出栈(删除栈顶元素,无返回值,O(1)) st.size(); // 获取元素个数(O(1)) st.empty(); // 判断是否为空(O(1)) // 遍历:栈不支持直接遍历,需通过出栈操作 while (!st.empty()) { cout << st.top() << " "; st.pop(); } return 0; }刷题常用场景:
- 括号匹配、单调栈问题
- 深度优先搜索(DFS)、回溯算法的辅助存储
4. 队列(queue)—— 先进先出(FIFO)
#include <queue> int main() { queue<int> q; // 核心操作 q.push(10); // 入队(尾部添加) q.push(20); q.front(); // 获取队首元素(不删除,O(1)) q.back(); // 获取队尾元素(不删除,O(1)) q.pop(); // 出队(删除队首元素,无返回值,O(1)) q.size(); // 获取元素个数(O(1)) q.empty(); // 判断是否为空(O(1)) // 遍历:队列不支持直接遍历,需通过出队操作 while (!q.empty()) { cout << q.front() << " "; q.pop(); } return 0; }刷题常用场景:
- 广度优先搜索(BFS)
- 任务调度、滑动窗口等问题
5. 映射(map)—— 键值对有序存储
#include <map> int main() { map<int, string> mp; // 键为int类型,值为string类型,自动按键升序排序 // 核心操作 mp[1] = "one"; // 插入键值对(键不存在则创建,存在则修改值) mp.insert({2, "two"}); // 插入键值对(键已存在则插入失败) mp.find(1); // 查找键,返回迭代器,未找到返回mp.end() mp.count(1); // 判断键是否存在,返回1(存在)或0(不存在) mp.erase(1); // 删除指定键的键值对(O(logn)) mp.size(); // 获取键值对个数(O(1)) mp.empty(); // 判断是否为空(O(1)) mp.clear(); // 清空所有键值对(O(n)) // 遍历 for (auto &pair : mp) { cout << pair.first << " : " << pair.second << endl; } return 0; }刷题常用场景:
- 统计元素出现次数(词频统计)
- 键值映射(如将字符串映射为数字)
6. 集合(set)—— 有序不重复元素存储
#include <set> int main() { set<int> st; // 自动升序排序,元素不重复 // 核心操作 st.insert(3); // 插入元素(O(logn),重复元素自动忽略) st.insert(1); st.find(3); // 查找元素,返回迭代器,未找到返回st.end() st.count(1); // 判断元素是否存在,返回1或0 st.erase(1); // 删除元素(O(logn)) st.size(); // 获取元素个数(O(1)) st.empty(); // 判断是否为空(O(1)) // 遍历 for (int num : st) { cout << num << " "; } return 0; }刷题常用场景:
- 去重操作
- 查找元素是否存在(比数组遍历高效)
三、常用算法(STL algorithm 库)
1. 排序(sort)—— 高频中的高频
#include <vector> #include <algorithm> int main() { vector<int> vec = {3,1,4,2,5}; // 默认升序排序 sort(vec.begin(), vec.end()); // 降序排序(Lambda表达式) sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); // 对数组排序 int arr[] = {5,3,1,2,4}; sort(arr, arr + 5); // 数组首地址和尾后地址 return 0; }2. 查找(binary_search)—— 二分查找
#include <vector> #include <algorithm> int main() { vector<int> vec = {1,2,3,4,5}; // 二分查找要求容器已排序 // 查找元素是否存在,返回bool值 bool exists = binary_search(vec.begin(), vec.end(), 3); // 查找第一个大于等于目标值的迭代器 auto lower = lower_bound(vec.begin(), vec.end(), 3); // 查找第一个大于目标值的迭代器 auto upper = upper_bound(vec.begin(), vec.end(), 3); return 0; }3. 其他常用算法
#include <vector> #include <algorithm> #include <numeric> int main() { vector<int> vec = {1,2,3,4,5}; // 反转容器 reverse(vec.begin(), vec.end()); // 填充容器 fill(vec.begin(), vec.end(), 0); // 求和(需包含numeric头文件) int sum = accumulate(vec.begin(), vec.end(), 0); // 查找元素第一次出现的迭代器 auto it = find(vec.begin(), vec.end(), 3); return 0; }四、刷题常用技巧
1. 快速初始化数组 / 容器
// 向量初始化为全0 vector<int> vec(100, 0); // 二维向量初始化(n行m列,全0) int n = 5, m = 3; vector<vector<int>> dp(n, vector<int>(m, 0));2. 处理大数取模
const int MOD = 1e9 + 7; long long res = (a + b) % MOD; // 避免溢出,先转long long再取模3. 迭代器简化书写
// 用auto自动推导迭代器类型,无需手动写vector<int>::iterator vector<int> vec = {1,2,3}; for (auto it = vec.begin(); it != vec.end(); it++) { cout << *it << " "; }五、总结
- 核心基础:掌握输入输出优化、变量类型(尤其是
long long)、循环与条件判断,是刷题的前提。 - 容器为王:
vector、string、stack、queue、map、set是算法刷题的核心工具,需熟练掌握其常用操作。 - 算法封装:STL 的
sort、binary_search等算法能大幅简化代码,提升效率。 - 实战优先:语法学习需结合具体算法题目,通过刷题巩固用法,才能真正掌握并灵活运用。
通过以上语法的学习,你已经具备了 C++ 算法刷题的基本能力,后续只需针对具体算法类型(如贪心、动态规划、图论等)进行专项训练即可。
我是千寻, 这期内容到这里就结束了,我们有缘再会😂😂😂 !!!