代码
#include
#include
vector <int> a; //一维动态数组
vector <int> b[777];//第一维长777第二位长度动态变化的数组
vector是一个空间能够动态变化的数组,当需要加n个元素时vector会申请2n长度的数组。当当前长度小于等于申请长度的4分之1时,vector会缩小一半的长度。
vector不支持随机插入,但是支持随机访问,元素的删减一般在末尾进行;
插入与删除
a.push_back(x);//把x插入队尾
a.pop_back();//把a尾部的数删除
长度与判空
a.size();//返回当前vector的实际长度,为0时vector为空
vector数组是以a[0]开头的,所以如果用size访问队尾的话要-1;
a.empty();判断当前vector是否为空,如果为空返回1否返回0;
清空
a.clear();清空vector数组;
访问
a.begin();访问vector第一个元素
a.end();访问vector尾部元素
a.front();访问第一个元素 等价于a[0]
a.back();访问最后一个元素等价于a[a.siez() -1]
代码
#inlcude
#inlcude
queue<int> q;//循环队列
priority_queue<int> q;//大根堆
priority_queue< pair<int, int> > q; //二元队列 q.top().first为第一元, q.top().second为第二元
//比较大小时二元队列以第一元为主关键字,第二元为次关键字
//插入时用q.push(make_pair(x,y));来插入x,y;
循环队列有着先进先出的性质,支持访问队头和队尾,但是出队时只能是从队头出队,入队时只能从队尾入队
入队
q.push(x)
出队
q.pop();
访问队头
q.front();
访问队尾
q.back();
插入元素 的方式
q.push();
提取队头
int x = q.top();
弹出队头
q.pop();
代码
std :: priority_queue<int> q;
一个大根堆,每次队头都会弹出最大的,那么对于一个int类型的数,如果我们每次把它的相反数入队,出队时也取相反数。
在优先队列中,存进去原本最小的数,就成了最大的数,这样就相当于是一个小根堆了。
代码
std :: priority_queue<int> q;
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
int x;
scanf("%d", &x); q.push(-x);
}
while(!q.empty()){
int x;
x = -q.top(); q.pop();
printf("%d\n",x);
}
return 0;
}
重载运算符是比较通用的一种实现小根堆的方法。
建立自定义结构体,重载小于号。
代码
struct cmp{
bool operator()(const int &a, const int &b){
return a>b;
}
}
std :: priority_queue<int, vector<int>, cmp>;
这样的话堆在使用<号时会认为左边的更大,就相当于将 “<” 改成 “>” 使用
在使用优先队列时因为是队列所以不支持随机访问,每次只能访问队头。
这里只对和堆有关的操作加了注释,要想看dijkstra堆优化更具体解释的话可以到这里看
代码
#include
#define MAXN 100010
#define INF 0x3f3f3f3f
struct node{
int y,z,ne;
}e[MAXN];
int lin[MAXN], len = 0;
inline addedg(int x, int y, int z){
e[++len].y = y; e[len].z = z; e[len].ne = lin[x]; lin[x] = len;
}
int dis[MAXN],vis[MAXN];
priority_queue< pair<int, int > > q;//定义一个二元堆
void dijkstra(){
memset(dis, INF, sizeof(dis));
memset(vis, false, sizeof(vis));
while(!q.empty()){
int x = q.top().second; q.pop();//取出当前节点,出队
if(vis[x]) continue;
vis[x] = true;
for(int i = lin[x]; i ; i = e[i].ne){
int y = e[i].y, z = e[i].z;
if(dis[y] > dis[x] + z){
dis[y] = dis[x] + z;
q.push(make_pair(-dis[y], y));//小根堆第一种写法
}
}
}
}
双端队列是一个支持在两端高效插入或删除元素的连续线性储存空间。
双端队列支持队头和队尾插入,同时也支持随机访问。
#inlcude
#inlcude
std :: deque< int > q;
访问队头
q.begin();//类似vector返回的是迭代器
q.front();类似queue
访问队尾
q.end();类似vector返回的是迭代器
q.back();类似queue
推荐用front和back因为begin和end要用迭代器
插入元素
q.push_back(x);插入队尾
q.push_front(x);插入队头
出队
q.pop_front()队头出队
q.pop_back();队尾出队
清空
q.clear();
#include
std :: deque<int> q1;//定义两个双端队列q1,q2
std :: deque<int> q2;
std :: deque<int> :: iterator it; //定义双端队列的两个迭代器
std :: deque<int> :: iterator is;//begin和end返回的是头尾迭代器。
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
int x;
scanf("%d", &x);
q1.push_front(x);//从队头插入q1
q2.push_back(x);//从队尾插入q2
}
//比较begin,end和front,back
it = q1.begin(), is = q2.begin(); //读取q1,q1头部迭代器的值
printf("begin1 = %d begin2 = %d ", *it, *is);//输出,*表示解除引用
printf("front1 = %d front2 = %d\n", q1.front(), q2.front());//输出队头的值
it = q1.end(), is = q2.end();//读取q1,q2尾部迭代器的值
printf("end1 = %d end2 = %d ", *it, *is);
printf("back1 = %d back2 = %d\n", q1.back(), q2.back());//输出队尾的值
//输出两个双端队列q1,q2
//把长度开两倍后能看见从队头插入的q1会在超出n长度后面两个数会出错
for(int i = 0; i < (n << 1); ++i){
printf("q1 = %d q2 = %d\n", q1[i], q2[i]);
}printf("\n");
printf("size1 = %d size2 = %d\n", q1.size(), q2.size());//输出长度
q1.clear();//清空队列
q2.erase(q2.begin() + 1);//删除队头后一个数
printf("size1 = %d size2 = %d\n", q1.size(), q2.size());
//再次输出长度q1长度为0, q2长度减一
for(int i = 0; i < (n << 1); ++i){//再次输出双端队列,会发现q1数值依旧存在
//q2原队头后一个数消失,最后一个数变为0
printf("q1 = %d q2 = %d\n", q1[i], q2[i]);
}printf("\n");
return 0;
}