学习笔记---栈与队列

栈与队列

先用数组手搓一遍吧,直接用STL库就不用学了

先进后出,水桶加料

//模板
// tt表示栈顶
int stk[N], tt = 0;

// 向栈顶插入一个数
stk[ ++ tt] = x;

// 从栈顶弹出一个数
tt -- ;

// 栈顶的值
stk[tt];

// 判断栈是否为空,如果 tt > 0,则表示不为空
if (tt > 0)
{

}
//实测练习
#include<iostream>
using namespace std;

const int N = 1e5+10;
int q[N];
int tt=0;

int main(){
    int num,n;
    string s;
    cin>>num;
    
    while(num--){
        cin>>s;
        if(s=="push") {
            cin>>n;
            q[++tt]=n;
        }
        if(s=="pop") tt--;
        if(s=="empty"){
            if(tt>0) cout<<"NO"<<endl;
            else cout<<"YES"<<endl;
        } 
        if(s=="query") {
            cout<<q[tt]<<endl;
        }
    }
    return 0;
}
//经典题型,表达式求值,构建数值栈和操作符栈
#include<iostream>
#include <string>
#include<unordered_map>

using namespace std;

const int N = 1e5+10;
int a[N],tt1=0,tt2=0;
char b[N];

unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };

void eval(){
    int x = a[--tt1];
    int y = a[--tt1];
    char p = b[--tt2];
    int r=0;
    
    if (p == '+') r = y + x;
    if (p == '-') r = y - x;
    if (p == '*') r = y * x;
    if (p == '/') r = y / x;
    
    a[tt1++] = r;
    //cout<<r<<endl;
}

int main(){
    string s;
    cin>>s;
    //cout<<s;
    
    for(int i = 0;i<s.size();i++){
        if(isdigit(s[i])){
            int x=0,j=i;
            while(j<s.size()&&isdigit(s[j])){
                x = x*10+(s[j]-'0');
                j++;
            }
            a[tt1++]=x;
            //cout<<x;
            i=j-1;
        }
        else if(s[i]=='('){
            b[tt2++]='(';
        }
        else if(s[i]==')'){
            while(tt2>0&&b[tt2-1]!='(') eval();
            tt2--;
        }
        else{
            while(tt2> 0 && h[b[tt2-1]]>=h[s[i]]) eval();
            b[tt2++]=s[i];
            //cout<<s[i];
        }
    }
    while(tt2>0) eval();
    cout<<a[tt1-1]<<endl;
    return 0;
}

队列

先进先出,没底的桶

// hh 表示队头,tt表示队尾
int q[N], hh = 0, tt = -1;

// 向队尾插入一个数
q[ ++ tt] = x;

// 从队头弹出一个数
hh ++ ;

// 队头的值
q[hh];

// 判断队列是否为空,如果 hh <= tt,则表示不为空
if (hh <= tt)
{

}
//实例测试
#include<iostream>
using namespace std;

const int N = 1e5+10;
int q[N],hh,tt=-1;

int main(){
    int num,n;
    string s;
    cin>>num;
    while(num--){
        cin>>s;
        if(s=="push"){
            cin>>n;
            q[++tt]=n;
        }
        if(s=="pop"){
            hh++;
        }
        if(s=="empty"){
            if(hh<=tt) cout<<"NO"<<endl;
            else cout<<"YES"<<endl;
        }
        if(s=="query"){
            cout<<q[hh]<<endl;
        }
    }
    return 0;
}

单调栈

感觉很详细的介绍:[数据结构]——单调栈-CSDN博客

//常见模型:找出每个数左边离它最近的比它大/小的数
int tt = 0;
for (int i = 1; i <= n; i ++ )
{
    while (tt && check(stk[tt], i)) tt -- ;
    stk[ ++ tt] = i;
}
//测试实例输出每个数左边第一个比它小的数,如果不存在则输出 −1
#include<iostream>
using namespace std;

const int N = 1e5+10;
int a[N],tt;

int main(){
    int num,n;
    scanf("%d",&num);
    
    for(int i = 0;i<num;i++){
        scanf("%d",&n);
        while(tt&&a[tt]>=n) tt--;
        if(tt) printf("%d ",a[tt]);
        else printf("-1 ");
        
        a[++tt] = n;
    }
    return 0;
}

单调队列

主要解决滑动窗口的问题

//常见模型:找出滑动窗口中的最大值/最小值
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
    while (hh <= tt && check_out(q[hh])) hh ++ ;  // 判断队头是否滑出窗口
    while (hh <= tt && check(q[tt], i)) tt -- ;
    q[ ++ tt] = i;
}
//滑动窗口经典例题
#include<iostream>
using namespace std;

const int N = 1e6+10;
int a[N],q[N];


int main(){
    int num,k;
    scanf("%d%d",&num,&k);
    
    for(int i = 0;i<num;i++) scanf("%d",&a[i]);
    
    int hh=0,tt=-1;
    for(int i = 0;i<num;i++){
        if(hh<=tt&&i-k+1>q[hh]) hh++;
        while(hh<=tt&&a[q[tt]]>=a[i]) tt--;
        q[++tt]=i;
        if(i>=k-1) printf("%d ",a[q[hh]]);
    }
    
    printf("\n");
    
    hh=0,tt=-1;
    for(int i = 0;i<num;i++){
        if(hh<=tt&&i-k+1>q[hh]) hh++;
        while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
        q[++tt]=i;
        if(i>=k-1) printf("%d ",a[q[hh]]);
    }
    
    return 0;
}

vscode整理

在这里插入图片描述

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值