栈与队列_基础1
栈与队列
- 栈:具有后进先出(Last In First Out)特性的线性表
//stack 栈
int sta[N], head=0; // 数组模拟栈,head 指向栈顶
sta[++head] = x; // 入栈
--head; // 出栈
if(head) // 栈不为空
sta[head]; // 栈顶
- 队列:具有先进先出(First In First Out)特性的线性表
// queue 队列, front 队首, tail 队尾
int que[N], front=0, tail=-1;
que[++tail] = x; // 入队
++front; // 出队
que[front]; //队头
if(front <= tail) //队列不为空
P1739 表达式括号匹配
表达式有英文字母(小写)、运算符(+
、-
、*
、/
)和左右小(圆)括号构成,以 @
作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配;
- 若匹配,则输出
YES
; - 否则输出
NO
。
表达式长度小于 \(255\),左圆括号少于 \(20\) 个。
样例输入
2*(x+y)/(1-x)@
样例输出
YES
分析
统计左括号的数量 h,如果出现右括号,那么左括号的数量 h-1。
合法的情况下:h 永远 ≥0,且最后 h=0。
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10;
int main(){
string s; cin>>s;
int h=0;
for(int i=0; i<s.size(); i++){
if(s[i]=='(') h++;
else if(s[i]==')'){
h--;
if(h < 0) break;
}
}
if(h==0) cout<<"YES";
else cout<<"NO";
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
char sta[N]; //stack 栈
int head=0; // 数组模拟栈,head 指向栈顶
int main(){
string s; cin>>s;
bool flag=1; // 假设原本括号是匹配的
for(int i=0; i<s.size(); i++){
if(s[i]=='(') sta[++head]=s[i];
else if(s[i]==')'){
if(head) head--; // 出栈
else { // 空栈, 无法出栈,括号不匹配
flag=0; break;
}
}
}
if(head) flag=0;
if(flag) cout<<"YES";
else cout<<"NO";
return 0;
}
P1449 后缀表达式
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:\(\texttt{3*(5-2)+7}\) 对应的后缀表达式为:\(\texttt{3.5.2.-*7.+@}\)。在该式中,@
为表达式的结束符号。.
为操作数的结束符号。
数据保证,\(1 \leq |s| \leq 50\),答案和计算过程中的每一个值的绝对值不超过 \(10^9\)。
样例输入
3.5.2.-*7.+@
样例输出
16
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
int sta[N], head=0, t=0;
int main(){
string s; cin>>s;
for(int i=0; i<s.size(); i++){
if(s[i] >='0' & s[i]<='9')
t = t*10 + s[i]-'0';
else if(s[i]=='.'){
sta[++head] = t; t=0; // t需要归 0
}else {
if(s[i]=='@') break; // 退出放最前面
int a=sta[head]; head--;
int b=sta[head]; head--;
if(s[i]=='+') sta[++head] = a+b;
if(s[i]=='-') sta[++head] = b-a;//注意先后
if(s[i]=='*') sta[++head] = a*b;
if(s[i]=='/') sta[++head] = b/a;
}
}
cout<<sta[head];
return 0;
}
P1981 [NOIP2013 普及组] 表达式求值
给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。
输入一行,为需要你计算的表达式,所有参与运算的数字均为 \(0\) 到 \(2^{31}-1\) 之间的整数。
输入数据保证这一行只有 \(0-9\)、\(+\)、$ \times$ 这 $12 $种字符。
对于 \(100\%\) 的数据,\(0≤\) 表达式中加法运算符和乘法运算符的总数 \(≤100000\)。
注意:当答案长度多于 \(4\) 位时,请只输出最后 $ 4$ 位,前导 $ 0$ 不输出。
样例输入
1+1*3+4
样例输出
8
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
LL sta[N], head=0, mod=1e4;
// (a+b) % p = (a%p+b%p) % p;
int main(){
LL a,b; char ch;
cin>>a; sta[++head]=a%mod;
while(cin>>ch>>b){
if(ch=='+') sta[++head]=b%mod;
if(ch=='*'){
a = sta[head--];
sta[++head] = a*b%mod;
}
}
LL res=0;
for(int i=1; i<=head; i++) res=(res+sta[i])%mod;
cout<<res;
return 0;
}
B3616 【模板】队列
请你实现一个队列(queue),支持如下操作:
push(x)
:向队列中加入一个数 \(x\)。pop()
:将队首弹出。如果此时队列为空,则不进行弹出操作,并输出ERR_CANNOT_POP
。query()
:输出队首元素。如果此时队首为空,则输出ERR_CANNOT_QUERY
。size()
:输出此时队列内元素个数。
数据范围:\(n\leq 10000\),且被插入队列的所有元素值是 \([1, 1000000]\) 以内的正整数。
输入格式
第一行,一个整数 \(n\),表示操作的次数。
接下来 \(n\) 行,每行表示一个操作。格式如下:
1 x
,表示将元素x
加入队列。2
,表示将队首弹出队列。3
,表示查询队首。4
,表示查询队列内元素个数。
输出格式
输出若干行,对于每个操作,按「题目描述」输出结果。
每条输出之间应当用空行隔开。
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
int que[N], front=0, tail=-1;
void push(int x){
que[++tail] = x;
}
void pop(){
if(front>tail) cout<<"ERR_CANNOT_POP"<<endl;
else ++front; // 出队
}
void query(){
if(front>tail) cout<<"ERR_CANNOT_QUERY"<<endl;
else cout<<que[front]<<endl;
}
int size(){
return tail-front+1;
}
int main(){
//freopen("data.in", "r", stdin);
int n,op,x; cin>>n;
while(n--){
cin>>op;
if(op==1) cin>>x,push(x);
if(op==2) pop();
if(op==3) query();
if(op==4) cout<<size()<<endl;
}
return 0;
}
P1996 约瑟夫问题
\(n\) 个人围成一圈,从第一个人开始报数,数到 \(m\) 的人出列,再由下一个人重新从 \(1\) 开始报数,数到 \(m\) 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
数据范围:\(1 \le m, n \le 100\)
输入两个整数 \(n,m\)。
输出一行 \(n\) 个整数,按顺序输出每个出圈人的编号。
样例输入
10 3
样例输出
3 6 9 2 7 1 8 5 10 4
参考程序
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;
int que[N], front=0, tail=-1;
int main() {
int n, m, cnt=0; cin>>n>>m;
for(int i=1; i<=n; i++) que[++tail] = i;
while(front <= tail) {
++cnt;
if(cnt%m==0) cout<<que[front]<<" "; // 杀掉
else que[++tail] = que[front]; // 没杀掉
++front;
}
return 0;
}