栈——竞赛应用小结

目录

一、概念

二、图示说明

1.数组模拟栈

2.数组模拟单调栈

三、操作实现

1.栈

a.插入元素到栈顶

b.删除栈顶元素

c.判断栈是否为空

d.返回栈顶元素

2.单调栈

a.维持单调栈

四、例题说明

1.栈

a.题目描述

b.解题思路

c.代码实现

2.单调栈

a.题目描述

b.解题思路

c.代码实现


一、概念

概念来源:

栈:栈是 OI 中常用的一种线性数据结构,栈的修改是按照后进先出的原则进行的,因此栈通常被称为是后进先出(last in first out)表,简称 LIFO 表。

单调栈:单调栈即满足单调性的栈结构,其只在一端进行进出。

二、图示说明

1.数组模拟栈

tt:指向栈顶所在的位置

栈示意图

2.数组模拟单调栈

tt:指向栈顶位置

栈内元素满足单调增或单调减的

单调栈示意图

三、操作实现

1.栈

a.插入元素到栈顶

栈顶位置后移

插入元素到到栈顶

int stk[N]; ///用数组模拟栈
int tt; ///记录单前栈顶的位置

void push_x(int x){
    stk[++tt]=x; ///先让栈顶位置后移,在插入元素(个人习惯栈顶位置从1开始)
}

b.删除栈顶元素

先删除栈顶元素

再将栈顶位置向前移动

void pop(){
   ///先将栈顶元素删除,然后再将栈顶位置先前移(删除元素不一定都赋为0,赋成插入元素范围外的数即可)
    stk[tt--]=0;
}

c.判断栈是否为空

bool empty(){
    if(tt>0)    return false; ///因为栈顶位置从1开始计算,当栈顶位置小于1时栈为空
    else return true;
}

d.返回栈顶元素

栈顶元素,即当前栈顶位置所在的元素

int query(){
    return stk[tt]; ///返回当前栈顶位置的元素即可
}

2.单调栈

以单调递增的情况为例

a.维持单调栈

初始状态

 

插入一个新的元素x,且x小于x3,大于x2

 

栈顶位置前移,进行某种操作
将新元素x,插入到其合适的位置上

 

 

int x;
cin >>x; ///插入一个元素x
while(tt&&stk[tt]>=x)    tt--;///当栈不为空,同时栈顶元素大于新元素x时,将栈顶位置向前移
if(tt>0)   (某种操作); ///此时若栈不为空,则说明找到一个元素比x小
stk[++tt]=x; ///然后将新元素x插入到栈中
 ///单调栈存储的数据,由底到顶逐渐增大,栈底为最小的元素

四、例题说明

1.栈

a.题目描述

题目来源:acwing

实现一个栈,栈初始为空,支持四种操作:

  1. push x – 向栈顶插入一个数 x;
  2. pop – 从栈顶弹出一个数;
  3. empty – 判断栈是否为空;
  4. query – 查询栈顶元素。

现在要对栈进行 M 个操作,其中的每个操作 3 和操作 4 都要输出相应的结果。

输入格式

第一行包含整数 M,表示操作次数。

接下来 M 行,每行包含一个操作命令,操作命令为 push xpopemptyquery 中的一种。

输出格式

对于每个 empty 和 query 操作都要输出一个查询结果,每个结果占一行。

其中,empty 操作的查询结果为 YES 或 NOquery 操作的查询结果为一个整数,表示栈顶元素的值。

数据范围

1≤M≤100000,
1≤x≤1e9
所有操作保证合法。

输入样例:

10
push 5
query
push 6
pop
query
pop
empty
push 4
query
empty

输出样例:

5
5
YES
4
NO

b.解题思路

思路:按题目要求实现四种操作

c.代码实现

#include<iostream>

using namespace std;

const int N=1e5+10;

int stk[N]; ///用数组模拟栈
int tt; ///记录单前栈顶的位置

void push_x(int x){
    stk[++tt]=x; ///先让栈顶位置后移,在插入元素(个人习惯)
}

void pop(){
    ///先将栈顶元素删除,然后再将栈顶位置先前移(删除元素不一定都赋为0,赋成插入元素范围外的数即可)
    stk[tt--]=0;
}

bool empty(){
    if(tt>0)    return false; ///因为栈顶位置从1开始计算,当栈顶位置小于1时栈为空
    else return true;
}

int query(){
    return stk[tt]; ///返回当前栈顶位置的元素即可
}

int main(){
    int m;
    cin >>m;
    while(m--){
        string op;
        cin >>op;
        int x;
        if(op=="push"){
            cin >>x;
            push_x(x);
        }
        else if(op=="pop"){
            pop();
        }
        else if(op=="empty"){
            if(empty()) puts("YES");
            else puts("NO");
        }
        else {
            cout <<query() <<endl;
        }
    }
    return 0;
}

2.单调栈

a.题目描述

题目来源:acwing

给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。

输入格式

第一行包含整数 N,表示数列长度。

第二行包含 N 个整数,表示整数数列。

输出格式

共一行,包含 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。

数据范围

1≤N≤1e5
1≤数列中元素≤1e9

输入样例:

5
3 4 2 7 5

输出样例:

-1 3 -1 2 2

b.解题思路

思路:用单调栈来维护栈内元素的单调递增性质,每增加一个元素维护一次,并按要求输出比新增元素小且距离最近的元素。

c.代码实现

#include<iostream>

using namespace std;

const int N=1e5+10;

int stk[N],tt;

int main(){
    int n;
    cin >>n;
    for(int i=0;i<n;i++){
        int x;
        cin >>x; 

        ///当栈不为空,同时栈顶元素大于新元素x时,将栈顶位置向前移
        while(tt&&stk[tt]>=x)    tt--;

        ///此时若栈不为空,则说明找到一个元素比x小,并将该元素输出
        if(tt>0)    cout <<stk[tt] <<' '; 
        else cout <<"-1 "; ///否则输出-1
        stk[++tt]=x; ///然后将新元素x插入到栈中
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值