yls的总结:
1.vector
#include <vector> 头文件
vector<int> a; 相当于一个长度动态变化的int数组
vector<int> b[233]; 相当于第一维长233,第二位长度动态变化的int数组
struct rec{…};
vector<rec> c; 自定义的结构体类型也可以保存在vector中
size/empty
size函数返回vector的实际长度(包含的元素个数),empty函数返回一个bool类型,表明vector是否为空。二者的时间复杂度都是O(1)。
所有的STL容器都支持这两个方法,含义也相同,之后我们就不再重复给出。
clear
clear函数把vector清空。
front/back
front函数返回vector的第一个元素,等价于*a.begin() 和 a[0]。
back函数返回vector的最后一个元素,等价于*==a.end() 和 a[a.size() – 1]。
push_back() 和 pop_back()
a.push_back(x) 把元素x插入到vector a的尾部。
b.pop_back() 删除vector a的最后一个元素。
迭代器
迭代器就像STL容器的“指针”,可以用星号“*”操作符解除引用。
一个保存int的vector的迭代器声明方法为:
vector<int>::iterator it;
vector的迭代器是“随机访问迭代器”,可以把vector的迭代器与一个整数相加减,其行为和指针的移动类似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器对应下标之间的距离。
begin/end
begin函数返回指向vector中第一个元素的迭代器。例如a是一个非空的vector,则*a.begin()与a[0]的作用相同。
所有的容器都可以视作一个“前闭后开”的结构,end函数返回vector的尾部,即第n个元素再往后的“边界”。*a.end()与a[n]都是越界访问,其中n=a.size()。
some code:
#include <iostream>
#include <vector>
//push_back/pop_back/clear/empty/size/front/back
using namespace std;
struct res
{
int x, y;
};
int main()
{
//存一维数组,a[]
vector<int> a;
for (int i = 0; i < 5; i ++)
{
a.push_back(i);
cout << a[i] << ' ';
}
cout << endl;
//empty()返回的是一个bool值
//如果数组为空,返回true,即1;如果数组不为空,则返回false,即0
int re = a.empty();
cout << re << endl;
//pop_back()删除数组中的最后一位数
a.pop_back();
for (int i = 0; i < a.size(); i ++)
{
cout << a[i] << ' ';
}
cout << endl;
//clear把数组清空
a.clear();
cout << a.empty() << endl;
//用vector存结构体
//总操作就是将q这个结构体存入vector p中
vector<res> p;
res q;
int x, y;
cin >> x >> y;
q.x = x;
q.y = y;
p.push_back(q);
//迭代器的声明:vector<int>::iterator
//迭代器与指针类似
for (vector<res>::iterator i = p.begin(); i != p.end(); i ++)//迭代器遍历,auto->vector<int>::iterator
{
cout << (*i).x << ' ' << (*i).y << endl;
}
for (auto j = p.begin(); j < p.end(); j ++)
{
cout << (*j).x << ' ' << (*j).y << endl;
}
cout << endl;
//用vector存二维数组,b[5][],一维固定,二维动态变化
vector<int> b[5];
int cnt = 1;
for (int i = 0; i < 5; i ++)
{
for (int j =0; j < 5; j ++)
{
b[i].push_back(cnt);
cout << b[i][j] <<' ';
cnt ++;
}
}
cout << endl;
//用vector来存字符数组,c[]
vector<char> c;
for (int i = 'a', j = 0; i <= 'z'; i ++, j ++)
{
c.push_back(i);
cout << c[j] << ' ';
}
cout << endl;
cout << "迭代器" <<endl;
vector<int> d;
for (int i = 0; i < 5; i ++)
{
d.push_back(i);
}
d.pop_back();
d.push_back(10);
vector<int>::iterator it = d.begin();
cout << *(it + 2) << endl; //与下面一种不相同
cout << *it + 2 << endl;//上面一种访问的是d[2],下面一种是a[0] + 2;
cout << *it + d.size() - 1 << endl;//访问最后一位数
cout << *(d.end() - 1 ) << endl;//访问最后一位数
cout << *d.end()<< endl;//访问越界,d.end()表示的是数组最后一位的下一个位置
while (it != d.end())
{
cout << *it << ' ';
it ++;
}
cout << endl;
//front/back
cout << d.front() << endl;//d[0]
cout << d.back() + 3 << endl;
cout << d.back() << endl;//d[d.size() - 1]
}
2.queue
#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;
循环队列 queue
push 从队尾插入
pop 从队头弹出
front 返回队头元素
back 返回队尾元素
优先队列 priority_queue
priority_queue<int> q; // 大根堆
priority_queue<int, vector<int>, greater<int> q; // 小根堆
push 把元素插入堆
pop 删除堆顶元素
top 查询堆顶元素(最大值)
some code:
#include <iostream>
#include <queue>
using namespace std;
int main()
{
//队列queue
//push/pop/front/back/empty
//push
queue<int> a;
for (int i = 0; i < 5; i ++)
{
a.push(i);//从队尾插入
}
//front/back
cout << a.front() << endl;//返回队头元素
cout << a.back() << endl;//返回队尾元素
a.pop();//把队头拿掉
cout << a.front() << endl;
a.pop();
cout << a.front() << endl;
cout << "清空一个数组:"<<endl;
queue<int> b;
for (int i = 0; i < 5 ; i ++)
{
b.push(i);
}
for (int i = 0; i < 5; i ++)
{
b.pop();
}
//empty
cout << b.empty() << endl;
//队列是无序的
queue<int> c;
c.push(9);
c.push(1);
c.push(2);
cout << c.front() << endl;
//队列里面装结构体
cout << "队列里面装结构体:" << endl;
//定义一个结构体
struct res
{
int x, y;
bool operator < (const res& t) const//结构体内必须定义小于号
{
return x < t.x;
}
};
queue<res> d;//定义一个结构体的队列
res p;
p.x = 1;
p.y = 2;
d.push(p);//将p这个结构体插到d这个队列中去
res q;
q.x = 4;
q.y = 3;
d.push(q);//将q这个结构体插入到d这个队列中去
cout << d.front().x << ' ' << d.front().y << endl;//输出队头
cout << d.back().x << ' ' << d.back().y << endl;//输出队尾
d.pop();//将队头删掉
cout << d.front().x << ' ' << d.front().y << endl;
cout << endl;
//优先队列priority_queue(大根堆)
priority_queue<int> m;//大根堆,堆顶为大根
//push/pop/top
//push
m.push(5);
m.push(1);
m.push(6);
m.push(2);
//top
cout << m.top() << endl;//输出最大值
//pop
m.pop();//删除堆顶
cout << m.top() << endl;
//大根堆里装结构体
struct ans
{
int v, w;
bool operator < (const ans& t) const //大根堆定义小于号
{
return v < t.v;
}
};
priority_queue<ans> n;
ans a1;
a1.v = 2;
a1.w = 1;
ans a2;
a2.v = 2;
a2.w = 0;
n.push(a1);
n.push(a2);
//先比较v,谁大谁堆顶
//v相同比较w,谁大谁堆顶
cout << n.top().v << ' ' << n.top().w << endl;
n.pop();//删除堆顶
cout << n.top().v << ' ' << n.top().w << endl;
cout << endl;
//优先队列priority_queue<int,vector<int>,greater<int>>(小根堆)
//push/top/pop
priority_queue<int, vector<int>, greater<int>> s;
//push
s.push(5);
s.push(1);
//top
cout << s.top() << endl;
//小根堆里装结构体
struct sum
{
int t1, t2;
bool operator > (const sum& t) const //小根堆定义大于号
{
return t1 > t.t1;
}
};
priority_queue<sum, vector<sum>, greater<sum>> k;
sum s1;
s1.t1 = 1;
s1.t2 = 5;
sum s2;
s2.t1 = 0;
s2.t2 = 9;
k.push(s1);
k.push(s2);
cout << k.top().t1 << ' ' << k.top().t2 << endl;
//pop
k.pop();
cout << k.top().t1 << ' ' << k.top().t2 << endl;
}
3.stack
头文件stack包含栈。声明和前面的容器类似。
push 向栈顶插入
pop 弹出栈顶元素
some code:
#include <iostream>
#include <stack>
//push/pop/top/empty/size
using namespace std;
int main()
{
stack<int> a;
//先进后出
//push向栈顶插入
a.push(1);
a.push(3);
a.push(2);
cout << a.top() << endl;
a.pop();//弹出栈顶元素
cout << a.top() << endl;
cout << a.empty() << endl;
cout << a.size() << endl;
}
4.deque
双端队列deque是一个支持在两端高效插入或删除元素的连续线性存储空间。它就像是vector和queue的结合。与vector相比,deque在头部增删元素仅需要O(1)的时间;与queue相比,deque像数组一样支持随机访问。
[] 随机访问
begin/end,返回deque的头/尾迭代器
front/back 队头/队尾元素
push_back 从队尾入队
push_front 从队头入队
pop_back 从队尾出队
pop_front 从队头出队
clear 清空队列
some code:
#include <iostream>
#include <deque>
using namespace std;
int main()
{
deque<int> a;
for (int i = 0; i < 5; i ++)
{
a.push_back(i);
}
cout << a.front() << endl;
cout << a.back() << endl;
deque<int> b;
for (int i = 0; i < 5; i ++)
{
b.push_front(i);
}
cout << a.front() << endl;
cout << a.back() << endl;
}
5.set 不含重复元素的哈希表
头文件set主要包括set和multiset两个容器,分别是“有序集合”和“有序多重集合”,即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部实现是一棵红黑树,它们支持的函数基本相同。
声明
set<int> s;
struct rec{…}; set<rec> s; // 结构体rec中必须定义小于号
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(logn)。
lower_bound/upper_bound
这两个函数的用法与find类似,但查找的条件略有不同,时间复杂度为 O(logn)。
s.lower_bound(x) 查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器。
s.upper_bound(x) 查找大于x的元素中最小的一个,并返回指向该元素的迭代器。
erase
设it是一个迭代器,s.erase(it) 从s中删除迭代器it指向的元素,时间复杂度为O(logn)
设x是一个元素,s.erase(x) 从s中删除所有等于x的元素,时间复杂度为O(k+logn),其中k是被删除的元素个数。
count
s.count(x) 返回集合s中等于x的元素个数,时间复杂度为 O(k +logn),其中k为元素x的个数。
迭代器
set和multiset的迭代器称为“双向访问迭代器”,不支持“随机访问”,支持星号(*)解除引用,仅支持”++”和--“两个与算术相关的操作。
设it是一个迭代器,例如set<int>::iterator it;
若把it++,则it会指向“下一个”元素。这里的“下一个”元素是指在元素从小到大排序的结果中,排在it下一名的元素。同理,若把it--,则it将会指向排在“上一个”的元素。
begin/end
返回集合的首、尾迭代器,时间复杂度均为O(1)。
s.begin() 是指向集合中最小元素的迭代器。
s.end() 是指向集合中最大元素的下一个位置的迭代器。换言之,就像vector一样,是一个“前闭后开”的形式。因此--s.end()是指向集合中最大元素的迭代器。
some code:
#include <iostream>
#include <set>
//size/empty/clear
//insert
//find
//lower_bound //查找大于等于x的最小元素
//upper_bound //查找大于x的最小元素
//erase//假设it为一个迭代器,erase(it),删除it迭代器所指元素
//count//返回的是x在集合中出现的个数
using namespace std;
int main()
{
//set(没有重复元素且有序)
set<int> a;
//insert
a.insert(1);
a.insert(3);
a.insert(1);
a.insert(2);
for (auto i = a.begin(); i != a.end(); i ++)
{
cout << *i << ' ';
}
//size
cout << endl;
cout << a.size() << endl;
//lower_bound/upper_bound
cout << *a.lower_bound(2) << endl;
cout << *a.upper_bound(2) << endl;
cout << a.count(1) << endl;
cout << "*" << endl;
a.erase(a.begin());
cout << *a.begin() << endl;
//利用find查找元素
//找到元素则返回的是该元素的迭代器
//没有找到,则a.find(n)==a.end(),返回的是a.end()
int n;
cin >> n;
if (a.find(n) != a.end())
{
cout << *a.find(n) << endl;
}
else
{
cout << "not find" << endl;
}
cout << endl;
struct res
{
int x, y;
bool operator < (const res& t) const
{
return x < t.x;
}
};
set<res> b;
res p;
p.x = 1;
p.y = 2;
res q;
q.x = 1;
q.y = 2;
res s;
s.x = 3;
s.y = 4;
b.insert(s);
b.insert(p);
b.insert(q);
//迭代器访问结构体时候,*去掉,加->
for (set<res>::iterator i = b.begin(); i != b.end(); i ++)
{
cout << i->x << ' ' << i->y << endl;
}
cout << endl;
for (auto i = b.begin(); i != b.end(); i ++)
{
cout << i->x << ' ' << i->y << endl;
}
cout << endl;
//multiset(有重复元素且有序)
multiset<int> c;
c.insert(1);
c.insert(1);
c.insert(2);
c.insert(3);
for (auto i = c.begin(); i != c.end(); i ++)
{
cout << *i << ' ';
}
cout << endl;
cout << c.count(1) << endl;
}
6.map//有序无重复元素
map容器是一个键值对key-value的映射,其内部实现是一棵以key为关键码的红黑树。Map的key和value可以是任意类型,其中key必须定义小于号运算符。
声明
map<key_type, value_type> name;
例如:
map<long, long, bool> vis;
map<string, int> hash;
map<pair<int, 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的二元组。
[]操作符
h[key] 返回key映射的value的引用,时间复杂度为O(logn)。
[]操作符是map最吸引人的地方。我们可以很方便地通过h[key]来得到key对应的value,还可以对h[key]进行赋值操作,改变key对应的value。
some code:
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main()
{
map<int, int> a;
a.insert({1, 2});
cout << a[1] << endl;
map<string, vector<int>> b;
b["xy"] = vector<int>({1, 2, 3, 4});
for (auto i = b["xy"].begin(); i != b["xy"].end(); i ++)
{
cout << *i << ' ';
}
cout << endl;
cout << endl;
cout << b["xy"][2] << endl;
cout << endl;
cout << (b.find("xy") == b.end()) << endl;
cout << *b["xy"].begin() << endl;
b["xy"].erase(b["xy"].begin());
cout << *b["xy"].begin() << endl;
}
7.unordered_map/unordered_set 无序哈希表
some code:
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<int, int> a;
for (int i = 0; i < 5; i ++)
{
a.insert({i, i});
}
for (int i = 0; i < 5; i ++)
{
cout << a[i] << ' ';
}
cout << endl;
}
#include <iostream>
#include <unordered_set>
//先入后出
using namespace std;
int main()
{
//unordered_set(存储不重复元素且无序)
unordered_set<int> a;
a.insert(2);
a.insert(1);
a.insert(3);
for (auto i = a.begin(); i != a.end(); i ++)
{
cout << *i << ' ';
}
cout << endl;
//unordered_multiset(可存储重复元素且无序)
unordered_multiset<int> b;
b.insert(1);
b.insert(1);
b.insert(3);
b.insert(2);
for (auto i = b.begin(); i != b.end(); i ++)
{
cout << *i << ' ';
}
cout << endl;
}
8.bitset
some code:
#include <iostream>
#include <bitset>
//set/reset/count
using namespace std;
int main()
{
bitset<1000> a;
a[0] = 1;
a[1] = 0;
a[2] = 1;
cout << a[0] << endl;
a.set(1);//把a[1] 变成 1
cout << a[1] << endl;
a.reset(0);//把a[0] 变成 0
cout << a[0] << endl;
cout << a.count() << endl;
}
注:本篇文章参考内容来自acwing!!!