学习笔记5||数据结构||栈+队列

本文介绍了栈和队列的基本概念,如先进后出(FIFO)特性,并探讨了它们在解决问题中的应用,如单调栈用于找出每个数左边最近的大/小数,单调队列用于求解滑动窗口中的最大值最小值。通过实例解析,阐述了如何利用单调性优化算法,提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先进后出;
基本操作:

#include<iostream>

using namespace std;

const int N=100010;

int stk[N],tt;
//插入
stk[++tt]=x;
//弹出
tt--;
//判断栈是否为空
if(tt>0) not empty
else empty;
//栈顶
stk[tt];

单调栈常见模型
找出每个数左边离它最近的比它大/小的数
int tt=0;
for(int i=1;i<=n;i++)
{
while(tt&&check(q[tt],i)) tt–;
stk[++tt]=i;
}

应用:单调栈
首先考虑暴力的求解方法,即用双指针来进行求解,最终把结果进行输出。用单调栈进行优化:用栈来存储已经遍历过的数。然后分析哪一些数永远不会作为答案进行输出,例如求取距离最小且小于的数,则存在逆序的话则第一点会被删掉。则最终栈中存放的就是单调的序列,是一个单调增的序列,当输入ai时,则在栈中找小于的数即可。

#include<iostream>

using namespace std;

const int N=100010;

int n;
int stk[N],tt;

int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        while(tt&&stk[tt]>=x) tt--;//栈不是空的,并且栈顶的元素是小于x的时候结束循环
        if(tt) cout<<stk[tt]<<endl;
        else cout<<-1<<endl;
        stk[++tt]==x;
    }
    return 0;
}

队列

先进先出

//对列
//在队尾插入元素,在队头弹出元素
int q[N],hh,tt=-1;

//插入
q[++tt]=x;

//弹出
hh++
//
if(hh<=tt) not empty
else empty;

//队头元素
q[hh];
//取队尾元素
q[tt];

单调队列常见模型
常见问题:找到滑动窗口中的最大值最小值
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;
}

应用:滑动窗口的最大值最小值
仍然是具有单调性,开一个数组来保存距离矩阵左端点的距离,实现保证点一直在区间的内部。所以在将数加入队列的时候,存入的一定是比队列的队尾大的数,
是一个单调递增的单调队列。然后输出队列的头即可。
简单描述就是:在队列中存储的是一个单调递增的数列,然后还要再开一个数组来记录当前数字与区间端点的距离,以保证该点仍然在滑动窗口内,最终将队列的head输出就是答案。

#include<iostream>

using namespace std;

const int N=1000010;

int n,k;
int a[N],q[N];


int main(){
    scanf("%d%d",&n,&k);
    
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    
    int hh=0,tt=-1;
    for(int i=0;i<n;i++){
        //判断队列是否已经滑出窗口
        if(hh<=tt&&i-k+1>q[hh]) hh++;//a中存放的是数值的大小,在队列q中存放的是下标;
        while(hh<=tt&&a[q[tt]]>=a[i]) tt--; 
        q[++tt]=i;
        if(i>=k-1) printf("%d",a[q[hh]]);
       
        //首先要保证队列不可以滑出窗口i-k+1>q[hh],即q[hh]是不断变大的,
        //然后维护队列为单调递增序列
        //都是最后记得把数添加到队列
    }
    return 0;
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值