C++ STL(标准模板库)基础巩固30题
由 eriktse 创建于 7/8/2024, 7:38:14 AM

目录(点击跳转):
vector
stack
queue
deque
priority_queue

STL专题

30题巩固C++STL(标准模板库)中的各种容器和算法的使用方法。

推荐引入万能头文件:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;//使用std命名空间

vector

创建vector

cpp 复制代码
vector<int> v; // 创建一个空的vector,元素类型为int
vector<int> v1(10); // 创建一个含有10个元素的vector,所有元素默认初始化为0
vector<int> v2(10, 42); // 创建一个含有10个元素的vector,所有元素初始化为42
vector<int> v3 = {1, 2, 3, 4, 5}; // 使用列表初始化创建一个vector

访问元素

cpp 复制代码
int x = v[0]; // 访问第一个元素
int y = v.at(1); // 使用at()函数访问第二个元素,at()会进行边界检查

修改元素

cpp 复制代码
v[0] = 10; // 修改第一个元素,O(1)
v.push_back(20); // 在vector末尾添加一个元素,O(1)
v.pop_back();//删除末尾元素,O(1),请注意保证vector非空

遍历vector

cpp 复制代码
for (int i = 0; i < v.size(); ++i) {
    cout << v[i] << ' ';
}
cout << endl;

// 或者使用范围for循环
for (int elem : v) {
    cout << elem << ' ';
}
cout << endl;

// 如果vector存储的是pair类型或结构体,C++17以上版本可以使用结构化绑定来枚举
vector<pair<int, int>> v_pair;
// &表示引用枚举,不加&就是默认拷贝枚举
for(const auto &[a, b] : v_pair){
  cout << x << ' ' << y << '\n';
}

查询vector的大小

cpp 复制代码
int size = v.size(); // 返回vector中元素的数量
//判断vector是否为空
if(v.empty()) ...
if(v.size()) ...

清空vector

cpp 复制代码
v.clear(); // 移除所有元素,size变为0,时间复杂度O(n)

stack

stack是栈,一种后进先出(Last In First Out)的容器,它仅维护栈顶,支持入栈(push)、查询栈顶(top)、出栈(pop)、查询大小(size)操作。

常用于“单调栈”、“括号匹配”、“dfs”、“Tarjan求强连通分量”、“波兰表达式(计算器)”等算法或数据结构中。

初始化

cpp 复制代码
stack<int> stk;//创建一个空栈,栈不允许列表初始化或填充相同元素
//但是可以从已有的栈进行拷贝构造
stack<int> stk2(stk);
stack<int> stk3 = stk2;

入栈

cpp 复制代码
stk.push(10);//stk = [10(top)]
stk.push(20);//stk = [10, 20(top)]
stk.push(50);//stk = [10, 20, 50(top)]
cout << stk.top() << '\n';//50, stk = [10, 20, 50(top)]

取出栈顶元素

在C++中,top()函数仅仅是取出栈顶元素,不会将栈顶元素pop()掉,请注意!

cpp 复制代码
cout << stk.top() << '\n';//50, stk = [10, 20, 50(top)]

出栈

讲个笑话:如果你问一个人push的反义词是什么,如果他说是pop,那么他肯定是一个程序员。

cpp 复制代码
//弹出栈顶元素,注意判断非空!
if(stk.size())stk.pop();//stk = [10, 20(top)]
cout << stk.top() << '\n';//20, stk = [10, 20(top)]

获取栈大小(元素个数),判空

cpp 复制代码
cout << stk.size() << '\n';
if(stk.empty())...//栈为空

清空栈

cpp 复制代码
while(stk.size())stk.pop();//时间复杂度O(n)

在stack中不允许遍历,但是如果我们手写栈(或者干脆用vector好了),就可以实现这个功能。

手写栈

手写栈非常简单,用一个top变量表示栈顶下标即可,以下标1作为栈底。

cpp 复制代码
int stk[N], top = 0;

//入栈
stk[++ top] = x;
//出栈
top --;
//取出栈顶元素
cout << stk[top] << '\n';
//获取大小
cout << top << '\n';
//判断是否为空
if(top)...//栈非空
//遍历栈
for(int i = 1;i <= top; ++ i)...
//甚至可以在单调栈上进行二分

queue

queue提供了先进先出(First In First Out)的数据结构。队列在尾部添加元素,在头部删除元素。

常见应用有:模拟、约瑟夫环、bfs、分支限界搜索、单调队列等算法。

创建队列

cpp 复制代码
queue<int> q; // 创建一个int类型的队列

添加元素(入队)

使用push()函数将元素添加到队列的尾部。

cpp 复制代码
q.push(10); // 将10添加到队列尾部
q.push(20);
q.push(30);

删除元素(出队)

使用pop()函数删除队列的头部元素。

cpp 复制代码
q.pop(); // 删除队列头部元素,即10

访问队列头部元素

使用front()函数获取队列头部元素的引用。

cpp 复制代码
int frontElement = q.front(); // frontElement 现在是20

访问队列尾部元素

使用back()函数获取队列尾部元素的引用。

cpp 复制代码
int backElement = q.back(); // backElement 现在是30

检查队列是否为空 / 获取队列大小

使用empty()函数检查队列是否为空。

cpp 复制代码
if (q.empty()) {
    cout << "队列是空的" << endl;
} else {
    cout << "队列不是空的" << endl;
}

int size = q.size(); // size 现在是2

示例代码
以下是一个使用queue的完整示例:

cpp 复制代码
#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> q;
    // 添加元素
    q.push(10);
    q.push(20);
    q.push(30);
    // 输出队列头部元素
    cout << "队列头部元素:" << q.front() << endl;
    // 删除队列头部元素
    q.pop();
    // 再次输出队列头部元素
    cout << "队列头部元素(删除后):" << q.front() << endl;
    // 输出队列大小
    cout << "队列大小:" << q.size() << endl;
    return 0;
}

运行上述代码,输出结果如下:

复制代码
队列头部元素:10
队列头部元素(删除后):20
队列大小:2

queuestack一样,不允许遍历。

deque

dequequeue的升级版,全称为double-ended queue,队头和队尾都支持入队和出队,同时还支持遍历,所有操作时间复杂度均为O(1)

常见应用是单调队列。

声明

cpp 复制代码
deque<int> dq;

常用操作

cpp 复制代码
dq.push_front(x);//在队头推入x
dq.push_back(x);//在队尾推入x

dq.front();//获取队头元素
dq.back();//获取队尾元素

//获取队列大小
dq.size();

//获取队列是否为空
dq.empty();

//以下两个操作注意判断队列非空
dq.pop_front();//弹出队头
dq.pop_back();//弹出队尾

遍历deque

cpp 复制代码
//用迭代器遍历
for(auto it = dq.begin(); it != dq.end(); it ++)
{
  cout << *it << ' ';
}

//用基于范围的for循环
for(const auto &val : dq)cout << val << ' ';

priority_queue

优先队列,也叫做“堆”,仅维护最大/最小的元素,可以在较小的时间复杂度内获取某个元素集合的最大或最小值。

优先队列常用于贪心、优化dp、构造、dijkstra、prim等问题或算法中,应用非常广泛。

声明

cpp 复制代码
//默认为大根堆
priority_queue<int> pq;
//改为小根堆
priority_queue<int, vector<int>, greater<int> > pq;


//自定义比较函数常用方法
//方法一:全局函数,传入函数指针用decltype转换
bool cmp(const int &u, const int &v){
  return u < v;//大根堆
}
priority_queue<int, vector<int>, decltype(&cmp) > pq(cmp);

//方法二:匿名函数用cmp变量存储,传入变量
auto cmp = [](const int &u, const int &v){
  return u < v;//大根堆
};

priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);

//方法三:struct重载()运算符
struct cmp{
	bool operator () (const int &u, const int &v){
	  return u < v;//大根堆
	}
};
priority_queue<int, vector<int>, cmp> pq;

常规操作

cpp 复制代码
//取出堆顶元素,时间复杂度O(1)
cout << pq.top() << '\n';//注意保证pq非空

//入堆,时间复杂度O(logn),n为堆内元素个数
pq.push(x);

//出堆,时间复杂度O(logn),n为堆内元素个数
pq.pop();//注意保证pq非空

//获取堆内元素个数,即堆的大小
cout << pq.size() << '\n';

优先队列为树形结构,不支持遍历(除非逐个出堆)。

map

set

multiset

sort

lower_bound和upper_bound

其他

题单信息
题单编号
2
题目数
7题
热度
3859
收藏数
16
完成情况
请登录后查看
分享优惠券赚收益