STL是提高C++编写效率的一个利器
1.#include<vector>
vector是变长数组,支持随机访问,不支持在任意位置o(1)插入。为保证效率,元素的增删一般应在末尾进行
声明
#include<vector> 头文件
vector<int>a; 相当于一个动态变化的Int数组
vector<int>a(3);长度为3的数组
vector<int>a(3,10);长度为3且初始化为10
vector<int>a[10];定义了10个vector
vector<int>b[233] 相当于一个第一维长233 第二位长度动态变化的int数组
struct rec{...};
vector<rec>c; 自定义的结构体类型也可以保存在vector中
vector<int>{nums[i],nums[j]} 初始化
size/empty
size函数返回vector 的实际长度(包含元素个数} empty函数返回一个bool类型
表明vector是否为空。二者的时间复杂度都是O(1).
所有的STL容器都支持这两个方法,含义也相同,之后我们就不再给出。
clear
作用是清空vector
迭代器
迭代器就像STL的指针,可以用*操作解除引用。
声明方法:
vector<int>::iterator it;
//取值
*it=
vector的迭代器是“随机访问迭代器”
可以把vector的迭代器与一个整数相加减,其行为和指针的移动相似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器对应下标之间的距离
begin/end
begin函数返回指向vector中的第一个元素的迭代器。例如a是一个非空的vector,
则*a.begin()与a[0]的作用相同。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int>a({1, 2, 3});
cout << a[0] << ' ' << *a.begin() << endl;
//输出都为1
return 0;
}
所有容器都可以视作一个前开后闭的结构,end函数返回vector的尾部,即第n个元素再往后的“边界”。*a.end()与a[n]都是越界访问,其中n=a.size()。
下面两份代码都遍历了vector<int>a,并输出它的元素。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int>a({1, 2, 3});
for (int i = 0; i < a.size(); i++)
cout << a[i] << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int>a({1, 2, 3});
for (vector<int>::iterator i = a.begin(); i != a.end() ; i++)
cout << *i << endl;
return 0;
}
其中 迭代器可以用auto优化
for (auto i = a.begin(); i != a.end() ; i++)
还有一种类似string的遍历也可以
for (int x : a)
cout << x << ' ';
front/back
用的比较少 front函数返回第一个元素
back函数返回最后一个元素 以下方式返回相同 相互等价
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int>a({1, 2, 3});
cout << a.front() << ' ' << a[0] << ' ' << *a.begin() << endl;
cout << a.back() << ' ' << a[a.size() - 1] << endl;
return 0;
}
push_back()和pop_back()
两个常用函数 push把元素插入到尾部
pop则是删除
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int>a({1, 2, 3});
a.push_back(4);
for (auto x : a)
cout << x << ' ';
cout << endl;//1234
a.pop_back();
for (auto x : a)
cout << x << ' ';
cout << endl;//123
return 0;
}
2.#include<queue>
头文件queue主要包括循环队列 queue和优先队列priority_queue两个容器
声明
queue<int>q;
struct rec{...}queue<rec>q; //结构体rec中必须定义小于号
priority_queue<int>q; //大根堆
priority_queue<int,vector<int>,greater<int>>q; //小根堆 重载大于号
priority_queue<pair<int,int>>q;
struct Rec {
int a, b;//重载
bool operator<(const Rec &t)const {
return a<t.a;
}
};
循环队列queue
push 从队尾插入
pop从队头弹出
front返回队头元素
back返回队尾元素
优先队列priority_queue(优先弹出大的数)
push 把元素入堆
pop 删除堆顶元素
top 查询堆顶元素(最大值)
队列没有clear函数
清空队列一般直接初始化
q=queue<int>();
3.#include<stack>
头文件stack包含栈。声明和前面的容器类似。
push 向栈顶插入
pop 弹出栈顶元素
4.#include<deque>
双端队列deque是一个支持在两端高效插入或者删除元素的连续线性存储空间。它就像是vector和queue的结合体。与vector相比,deque在头部增删元素仅仅需要O(1)的时间;与queue相比,deque像数组一样支持随机访问
begin/end 返回头/尾迭代器
front/back 队头/队尾元素
push_back 从队尾入队
push_front从队头入队
pop_back从队尾出队
5.#include<set>
头文件set主要包括set和multiset,分别是有序集合和有序多重集合,即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部实现是一颗红黑树,他们支持的函数基本相同。
声明
set<int>s;
struct rec{....};set<rec>s;//结构体中必须定义小于号
multiset<double>s;
size/empty/clear
与vector类似
迭代器
insert
s.insert(x)把一个元素x插入到集合s中,时间复杂度为O(logn)
在set中,若元素存在 则不会重复插入该元素,对集合的状态无影响
find
s.find(x)在集合s中查找等于x的元素,并返回指向该元素的迭代器。若不存在则返回s.end()。时间复杂度为O(k+logn)
lower bound/upper bound
这两个函数的用法与find类似,但查找的条件略有不同,时间复杂度为O(logn)
s.lower_bound(x)查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器
s.upper_bound(x)查找大于x元素中最小的一个,并返回指向该元素的迭代器。
erase
设it是一个迭代器,s.erase(x)从s中删除所有等于x的元素,时间复杂度为O(k+logn)
其中k为被删除的元素的个数
count
s,count(x)返回集合s中等于x的元素的个数,时间复杂度为O(k+logn),其中k为元素x的个数
6.#include<map>
map容器是一个键值对key-value的映射,其内部实现是一颗以key为关键码的红黑树。Map的key和value可以是任意类型,其中key必须定义小于运算符
声明
map<long long,bool>vis;
map<string,int>
map<pair<int>,vector<int>>test;
size/empty/clear/begin/end均与set类似
insert/erase
与set类似 ,但其参数均是pair<key_type,value_type>。
find
h.find(x)在变量名为h的map中查找key为x的二元组。
补充
pair
需要两个不同属性东西排序时常用
pair<int,string>a;
a={3,"chuizi"};
cout<<a.first<<' '<<a,second<<endl;
支持比较运算 以first为第一关键字 second为第二关键字
p=make_pair(10,"chuizi")