栈与队列_基础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;
}
posted @ 2022-11-24 09:39  HelloHeBin  阅读(61)  评论(0编辑  收藏  举报