今天讲一下STL里面的栈和队列的基本操作,栈和队列都是一种数据结构,他们的共同点是都是线性结构,当然,他俩也有不同的地方,栈是一种先进后出的数据结构,而队列则是一种先进先出的数据结构。
可以这样来说,队列就像一个羽毛球盒,从一边放进去就从另一边拿出来,如果从放进去的那一边一边拿,就会造成羽毛损坏,如图
而栈则可以看成一个乒乓球盒,也就是说乒乓球盒只有一个口,越先放进去就会被压到最下面,从而就会越后出来,如图
这道题虽然看起来有点难懂,但他确是一道栈的题目,也就是说,我们可以吧弹夹看做一个栈,子弹也就是元素,每将一个子弹放入弹夹,就相当于一个元素入栈,这道题目实际上就是在问下列哪一个出栈顺序是不合法的,我们遇到这样的题目可以画一个示意图:
A:
所以合法;
B:
所以合法。
C:
D:
这道题可以让我们更深刻的理解栈的基本概念。遇到这种题目,我们可以利用栈的概念解决,首先先找准目前没有进过栈的第一个数,然后将目前未进栈元素到我们刚刚找的那个元素全部依次进栈,然后查看出栈顺序是否合法,依次模拟,即可得出结果。
push 元素入栈
push | 元素入栈 |
---|---|
pop | 栈顶元素出栈 |
front | 获取栈底元素 |
size | 获取栈长度 |
empty | 栈判空 |
push | 元素入队列 |
---|---|
pop | 队尾元素出栈 |
front | 获取队头元素 |
size | 获取队列长度 |
empty | 队列判空 |
top | 获取队尾元素 |
题目描述
将一个数组中的值按逆序重新存放。例如,原来的顺序为 8 , 6 , 5 , 4 , 1 8,6,5,4,1 8,6,5,4,1。要求改为 1 , 4 , 5 , 6 , 8 1,4,5,6,8 1,4,5,6,8。
输入格式
输入为两行:第一行数组中元素的个数 n n n( 1 < n ≤ 100 1 \lt n \le 100 1<n≤100),第二行是 n n n 个整数,每两个整数之间用空格分隔。
输出格式
输出为一行:输出逆序后数组的整数,每两个整数之间用空格分隔。
样例 #1
样例输入 #1
5
8 6 5 4 1
样例输出 #1
1 4 5 6 8
这道题非常简单,其方法也很多,最常见的方法就是用数组存储,但是这道题的题意刚好符合我们的栈,为了拿栈练练手,这道题我们用栈做:
我们只需要利用栈先进后出的特点,将输入的数字依次入栈,最后在依次出栈输出即可:直接给代码
#include
using namespace std;
int i,a,x;
stack<int>h;
int main(){
ios::sync_with_stdio(false);
cin>>a;
for(i=0;i<a;i++){
cin>>x;
h.push(x);
}
for(i=0;i<a;i++){
x=h.top();
h.pop();
cout<<x<<" ";
}
}
题目描述
请你实现一个栈(stack),支持如下操作:
push(x)
:向栈中加入一个数 x x x。pop()
:将栈顶弹出。如果此时栈为空则不进行弹出操作,输出 Empty
。query()
:输出栈顶元素,如果此时栈为空则输出 Anguei!
。size()
:输出此时栈内元素个数。输入格式
本题单测试点内有多组数据
输入第一行是一个整数 T T T,表示数据组数。对于每组数据,格式如下:
每组数据第一行是一个整数,表示操作的次数 n n n。
接下来 n n n 行,每行首先由一个字符串,为 push
,pop
,query
和 size
之一。若为 push
,则其后有一个整数 x x x,表示要被加入的数, x x x 和字符串之间用空格隔开;若不是 push
,则本行没有其它内容。
输出格式
对于每组数据,按照「题目描述」中的要求依次输出。每次输出占一行。
样例 #1
样例输入 #1
2
5
push 2
query
size
pop
query
3
pop
query
size
样例输出 #1
2
1
Anguei!
Empty
Anguei!
0
提示
样例 1 解释
对于第二组数据,始终为空,所以 pop
和 query
均需要输出对应字符串。栈的 size 为 0。
数据规模与约定
对于全部的测试点,保证 1 ≤ T , n ≤ 1 0 6 1 \leq T, n\leq 10^6 1≤T,n≤106,且单个测试点内的 n n n 之和不超过 1 0 6 10^6 106,即 ∑ n ≤ 1 0 6 \sum n \leq 10^6 ∑n≤106。保证 0 ≤ x < 2 64 0 \leq x \lt 2^{64} 0≤x<264。
提示
Empty
不含叹号,Anguei!
含有叹号。这是一道普及模板题,这道题目是让我们用栈来实现一个栈,这听起来非常拗口,但做起来非常容易,只需要判断输入的是什么指令,在利用栈实现即可:
这道题需要注意一个地方,他会有很多次指令,再一次指令弄完以后,一定要记得清空栈哦!
//B3614【模板】栈
#include
using namespace std;
int n,i,j,k,x,z;
string c;
stack<int>h;
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(i=1;i<=n;i++){
cin>>k;
for(j=1;j<=k;j++){
for(z=1;z<=h.size();z++)//清空栈
h.top();
cin>>c;
if(c=="push"){
cin>>x;
h.push(x);
continue;
}
if(c=="pop"){
if(!h.size()){
cout<<"Empty"<<endl;
continue;
}
else
h.pop();
}
if(c=="query"){
if(h.size()==0){
cout<<"Anguei!"<<endl;
continue;
}
else {
cout<<h.top()<<endl;
continue;
}
}
if(c=="size")
cout<<h.size()<<endl;
}
}
}
题目描述
请你实现一个队列(queue),支持如下操作:
push(x)
:向队列中加入一个数 x x x。pop()
:将队首弹出。如果此时队列为空,则不进行弹出操作,并输出 ERR_CANNOT_POP
。query()
:输出队首元素。如果此时队首为空,则输出 ERR_CANNOT_QUERY
。size()
:输出此时队列内元素个数。输入格式
第一行,一个整数 n n n,表示操作的次数。
接下来 n n n 行,每行表示一个操作。格式如下:
1 x
,表示将元素 x
加入队列。2
,表示将队首弹出队列。3
,表示查询队首。4
,表示查询队列内元素个数。输出格式
输出若干行,对于每个操作,按「题目描述」输出结果。
每条输出之间应当用空行隔开。
样例 #1
样例输入 #1
13
1 2
3
4
1 233
3
2
3
2
4
3
2
1 144
3
样例输出 #1
2
1
2
233
0
ERR_CANNOT_QUERY
ERR_CANNOT_POP
144
提示
样例解释
首先插入 2
,队首为 2
、队列内元素个数为 1
。
插入 233
,此时队首为 2
。
弹出队首,此时队首为 233
。
弹出队首,此时队首为空。
再次尝试弹出队首,由于队列已经为空,此时无法弹出。
插入 144
,此时队首为 144
。
数据规模与约定
对于 100 % 100\% 100% 的测试数据,满足 n ≤ 10000 n\leq 10000 n≤10000,且被插入队列的所有元素值是 [ 1 , 1000000 ] [1, 1000000] [1,1000000] 以内的正整数。
这道题依旧是一道模板题,本题就比较仁慈了,不用每次清空队列,也省下了很多时间,且思路和上一道题一样,用一个队列模拟队列即可
#include
using namespace std;
string f;
int n,i,k;
queue<int>h;
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(i=1;i<=n;i++){
cin>>f;
if(f=="1"){
cin>>k;
h.push(k);
continue;
}
if(f=="2"){
if(h.size()==0){
cout<<"ERR_CANNOT_POP"<<endl;
continue;
}
else {
h.pop();
continue;
}
}
if(f=="3"){
if(h.size()==0){
cout<<"ERR_CANNOT_QUERY"<<endl;
continue;
}
else{
cout<<h.front()<<endl;
continue;
}
}
if(f=="4")
cout<<h.size()<<endl;
}
}
大家再学新知识点的时候,推荐大家去做一下洛谷上面的相应模板题,这样没有太大的思维难度,也能帮助你熟悉相应操作,难度适中,很适合入门!
今天就讲到这里了,下次再见!!!