目录
[楔子:C++ STL](#楔子:C++ STL)
[1.Vector 动态数组:](#1.Vector 动态数组:)
[2.Stack 栈:](#2.Stack 栈:)
[3.Queue 队列:](#3.Queue 队列:)
[4.Deque 双端队列:](#4.Deque 双端队列:)
[5.Map 映射:](#5.Map 映射:)
[6.Set 集合:](#6.Set 集合:)
[7.Pair 二元组:](#7.Pair 二元组:)
[8.String 字符串:](#8.String 字符串:)
[9.Array 数组:](#9.Array 数组:)
[10.Tuple 元组:](#10.Tuple 元组:)
楔子:C++ STL
STL = Standard Template Library(标准模板库)
可以理解为 C++ 自带的"工具箱",里面装好了常用的数据结构和算法,直接拿来用就行,不用自己从头写。
1.Vector 动态数组:
可变长数组,可以随时添加数值和删除元素。
cpp
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> v[3];
v[0].push_back(1);
v[0].push_back(1);
v[0].push_back(1);
v[1].push_back(2);
v[2].push_back(3);
v[2].push_back(3);
for(int i=0;i<3;i++) {
for(int j=0;j<v[i].size();j++) {
cout<<v[i][j]<<" ";
}
cout<<endl;
}
}
2.Stack 栈:
先进后出,后进先出的容器。
cpp
#include<iostream>
#include<stack>
using namespace std;
int main() {
stack<int> st;
st.push(10);
st.push(20);
st.push(30);
while (!st.empty()) {
int val_top = st.top();
cout<<val_top<<endl;
st.pop();
}
}
3.Queue 队列:
先进先出的容器。
cpp
#include<iostream>
#include<queue>
#include<deque> //双端队列
using namespace std;
int main() {
queue<int> q;
q.push(10);
q.push(20);
q.push(30);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
}
4.Deque 双端队列:
首尾都可插入和删除的队列为双端队列。
cpp
#include<iostream>
#include<queue>
#include<deque> //双端队列
using namespace std;
int main() {
queue<int> q;
q.push(10);
q.push(20);
q.push(30);
while (!q.empty()) {
cout << q.front() << endl;
q.pop();
}
}
5.Map 映射:
每个x对应一个y,而map是每个键对应一个值,与python的字典类型相似。
cpp
#include<iostream>
#include<map>
using namespace std;
int main() {
map<string,int> mp;
mp["apple"] = 4;
mp["banana"] = 3;
mp["coconut"] = 5;
for (auto i:mp) {
cout<<i.first<<" = "<<i.second<<endl;
}
}
6.Set 集合:
集合,元素不会重复,set容器里的元素自动从小到大排序。
cpp
#include<iostream>
#include<set>
using namespace std;
int main() {
set<int> s{8,8,58,2};//自动升序且去重
for (auto i:s) {
cout<<i<<" ";
}
}
7.Pair 二元组:
pair只含有两个元素,可以看作是只有两个元素的结构体。
cpp
#include <iostream>
using namespace std;
int main() {
// 最简洁的初始化
pair<int, int> p = {1, 2};
// pair 数组
pair<int, int> arr[3] = {{1, 2}, {3, 4}, {5, 6}};
// 打印
cout << p.first << " " << p.second << endl; // 输出:1 2
// 遍历打印
for (auto i : arr) {
cout << i.first << "," << i.second<<" ";
}
return 0;
}
8.String 字符串:
字符串类。
cpp
#include<iostream>
#include<string>
using namespace std;
int main() {
略;
}
9.Array 数组:
Array是C++ 11新增的容器,比vector效率要高。
cpp
#include<iostream>
#include<array>
using namespace std;
int main() {
array<int,5> arr{1,2,3,4,5};//一开始就固定
for (auto i : arr) {
cout << i << endl;
}
}
10.Tuple 元组:
可以把tuple理解为pair的扩展,tuple可以声明二元组,也可以声明三元组。
cpp
#include<iostream>
#include<tuple>
using namespace std;
int main() {
tuple<int,double,string> t{3,0.14,"Pi"};
//只能用get访问d
cout<<get<0>(t)<<endl;
cout<<get<1>(t)<<endl;
cout<<get<2>(t)<<endl;
}
一、基础算法(排序、查找)
排序:
1.冒泡排序
cpp
#include <iostream>
using namespace std;
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
cout << "排序后: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
2.选择排序
cpp
#include <iostream>
using namespace std;
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIdx = i; // 假设当前 i 是最小值的位置
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j; // 找到更小的,更新位置
}
}
// 交换
swap(arr[i], arr[minIdx]);
}
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
3.插入排序
cpp
#include <iostream>
using namespace std;
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i]; // 当前要插入的元素
int j = i - 1;
// 将比 key 大的元素都往后移
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key; // 插入到正确位置
}
}
int main() {
int arr[] = {12, 11, 13, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
4.快速排序
cpp
#include <iostream>
using namespace std;
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 选最后一个作为基准
int i = low - 1; // 小于基准的区域的边界
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return i + 1; // 返回基准的位置
}
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
5.归并排序
cpp
#include <iostream>
using namespace std;
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
// 创建临时数组
int L[n1], R[n2];
// 拷贝数据
for (int i = 0; i < n1; i++) L[i] = arr[left + i];
for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];
// 合并
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) arr[k++] = L[i++];
else arr[k++] = R[j++];
}
// 拷贝剩余元素
while (i < n1) arr[k++] = L[i++];
while (j < n2) arr[k++] = R[j++];
}
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
int main() {
int arr[] = {12, 11, 13, 5, 6, 7};
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
6.计数排序(特定场景)
cpp
#include <iostream>
#include <vector>
using namespace std;
void countingSort(int arr[], int n) {
// 找到最大值和最小值
int maxVal = arr[0], minVal = arr[0];
for (int i = 1; i < n; i++) {
maxVal = max(maxVal, arr[i]);
minVal = min(minVal, arr[i]);
}
int range = maxVal - minVal + 1;
vector<int> count(range, 0);
// 统计每个数出现的次数
for (int i = 0; i < n; i++) {
count[arr[i] - minVal]++;
}
// 按顺序输出
int idx = 0;
for (int i = 0; i < range; i++) {
while (count[i] > 0) {
arr[idx++] = i + minVal;
count[i]--;
}
}
}
int main() {
int arr[] = {4, 2, 2, 8, 3, 3, 1};
int n = sizeof(arr) / sizeof(arr[0]);
countingSort(arr, n);
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
7.基数排序(特定场景)
搜索:
1.线性搜索
cpp
#include <iostream>
using namespace std;
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
return i; // 找到返回下标
}
}
return -1; // 没找到
}
int main() {
int arr[] = {5, 3, 8, 6, 2, 7};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 6;
int result = linearSearch(arr, n, target);
if (result != -1) {
cout << "找到了,下标是: " << result << endl;
} else {
cout << "没找到" << endl;
}
return 0;
}
2.二分搜索(有序数组)
cpp
#include <iostream>
#include <vector>
#include <algorithm> // 给 sort 用
using namespace std;
// 迭代版本(推荐)
int binarySearch(int arr[], int n, int target) {
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止溢出
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
// 递归版本
int binarySearchRecursive(int arr[], int left, int right, int target) {
if (left > right) return -1;
int mid = left + (right - left) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target)
return binarySearchRecursive(arr, mid + 1, right, target);
else
return binarySearchRecursive(arr, left, mid - 1, target);
}
int main() {
int arr[] = {2, 5, 6, 8, 11, 15, 20};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 11;
// 二分搜索要求数组有序
// arr 已经有序,无序的话先 sort(arr, arr + n)
int result = binarySearch(arr, n, target);
if (result != -1) {
cout << "找到了,下标是: " << result << endl;
} else {
cout << "没找到" << endl;
}
return 0;
}
3.深度优先搜索(DFS)
cpp
#include <iostream>
#include <vector>
using namespace std;
// 用邻接表存储图
vector<vector<int>> graph;
vector<bool> visited;
// 递归 DFS
void dfsRecursive(int node) {
visited[node] = true;
cout << node << " "; // 访问当前节点
// 遍历所有邻居
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
dfsRecursive(neighbor);
}
}
}
// 栈实现 DFS(非递归)
void dfsStack(int start) {
vector<bool> visited(graph.size(), false);
stack<int> st;
st.push(start);
while (!st.empty()) {
int node = st.top();
st.pop();
if (visited[node]) continue;
visited[node] = true;
cout << node << " ";
// 把邻居压入栈(逆序可以保持顺序)
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
st.push(neighbor);
}
}
}
}
int main() {
// 创建图(邻接表)
int n = 6; // 节点数 0-5
graph.resize(n);
// 添加边(无向图)
graph[0] = {1, 2};
graph[1] = {0, 3, 4};
graph[2] = {0, 4};
graph[3] = {1, 5};
graph[4] = {1, 2, 5};
graph[5] = {3, 4};
// DFS 遍历(从节点0开始)
visited.assign(n, false);
cout << "递归 DFS: ";
dfsRecursive(0);
cout << endl;
cout << "栈 DFS: ";
dfsStack(0);
cout << endl;
return 0;
}
4.广度优先搜索(BFS)
cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void bfs(vector<vector<int>>& graph, int start) {
int n = graph.size();
vector<bool> visited(n, false);
queue<int> q;
visited[start] = true;
q.push(start);
while (!q.empty()) {
int node = q.front();
q.pop();
cout << node << " ";
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push(neighbor);
}
}
}
}
// BFS 求最短路径(无权图)
vector<int> bfsShortestPath(vector<vector<int>>& graph, int start, int target) {
int n = graph.size();
vector<bool> visited(n, false);
vector<int> prev(n, -1); // 记录前驱节点
queue<int> q;
visited[start] = true;
q.push(start);
while (!q.empty()) {
int node = q.front();
q.pop();
if (node == target) break;
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
prev[neighbor] = node;
q.push(neighbor);
}
}
}
// 构建路径
vector<int> path;
for (int at = target; at != -1; at = prev[at]) {
path.push_back(at);
}
reverse(path.begin(), path.end());
return path;
}
int main() {
// 创建图
int n = 6;
vector<vector<int>> graph(n);
graph[0] = {1, 2};
graph[1] = {0, 3, 4};
graph[2] = {0, 4};
graph[3] = {1, 5};
graph[4] = {1, 2, 5};
graph[5] = {3, 4};
// BFS 遍历
cout << "BFS: ";
bfs(graph, 0);
cout << endl;
// BFS 最短路径
vector<int> path = bfsShortestPath(graph, 0, 5);
cout << "0 到 5 的最短路径: ";
for (int node : path) {
cout << node << " ";
}
cout << endl;
return 0;
}
二、数据结构相关算法
-
数组:遍历、插入、删除、反转、前缀和、差分数组
-
链表:单链表(反转、合并、找环)、双向链表
-
栈:括号匹配、表达式求值、单调栈
-
队列:普通队列、循环队列、双端队列、单调队列(滑动窗口)
-
树:
-
二叉树(前/中/后序遍历、层序遍历)
-
二叉搜索树(BST)
-
最近公共祖先(LCA)
-
树的直径、深度计算
-
-
图操作:
-
图的存储(邻接矩阵、邻接表)
-
图的遍历(DFS、BFS)
-
最短路径(Dijkstra、Floyd)
-
拓扑排序、最小生成树(Kruskal、Prim)
-
三、数学相关算法
-
数论:
-
最大公约数(GCD)、最小公倍数(LCM)
-
素数判定、筛法(埃氏筛、欧拉筛)
-
快速幂
-
同余、模运算
-
-
概率:基本概率计算、期望
-
统计:均值、中位数、众数、方差(基础)
四、高级算法
-
动态规划:
-
背包问题(0/1背包、完全背包)
-
最长公共子序列(LCS)
-
最长上升子序列(LIS)
-
区间DP、状态压缩DP(基础)
-
-
贪心:区间调度、活动选择、哈夫曼编码、最小生成树的Prim/Kruskal也是贪心
-
分治:归并排序、快速排序、二分搜索、平面最近点对
五、算法优化
-
复杂度分析:
-
时间复杂度(大O表示法)
-
空间复杂度
-
常见复杂度:O(1), O(log n), O(n), O(n log n), O(n²), O(2ⁿ)
-
六、实际应用(结合业务场景设计算法)
-
模拟类问题(按照题目描述的流程写代码)
-
字符串处理(模式匹配、编辑距离、回文)
-
简单数据压缩/编码思想
-
模拟现实流程(如银行排队、任务调度)