模拟栈
C++中STL的栈:
stack<int> stk;
stk.push_back(1); //入栈
stk.top(); //返回栈顶元素
stk.pop(); //出栈
数组模拟栈定义:
const int N=1e5+10;
int stk[N],tp;
- stk[i]:表示栈中元素的值;
- tp:表示栈顶元素的下标。
栈初始化:
void init(){
tp=0;
}
- 当
tp=0
时表示栈为空。
入栈:
void push(int x){
stk[++tp]=x;
}
注意:
- 是从下标
1
开始存起。 - tp的值可以用来表示栈中元素的个数。
出栈:
void pop(){
--tp; //直接让tp往前移一位表示出栈
}
返回栈顶元素:
int top(){
return stk[tp]; //tp指向的就是栈顶元素的位置
}
判断栈是否为空:
bool isEmpty(){
if(tp>0) return false; //栈非空
return ture; //栈空
}
- tp不为0时,栈非空。
单调栈(栈的应用)
题目:给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。
#include<iostream>
using namespace std;
const int N=1E5+10;
int stk[N],tp;
int main(){
int n;
cin>>n;
while(n--){
int x;
cin>>x;
while(tp && stk[tp]>=x) tp--;
if(!tp) cout<<"-1 ";
else cout<<stk[tp]<<" ";
stk[++tp]=x;
}
return 0;
}
模拟队列
C++中STL的队列:
queue<int> q;
q.push(1); //入队
q.front(); //返回队头元素
q.pop(); //出队
数组模拟队列定义:
const int N=1e5+10;
int q[N],head,tail;
队列初始化:
void init(){
head=0;
tail=-1; //队尾下标要从-1开始
}
- 如果是循环队列,初始化
tail=0;
在队尾插入元素:
void push(int x){
q[++tail]=x;
}
取出队头元素:
int front(){
return q[head];
}
从队头弹出元素(出队):
void pop(){
++head;
}
判断队列是否为空:
bool isEmpty(){
if(head<=tail) return false; //队列非空
return true; //队列空
}
head>tail
时,队列为空。因此,初始化时:head=0; tail=-1;
。
滑动窗口(队列的应用)
题目:有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。
确定滑动窗口位于每个位置时,窗口中的最大值和最小值。
#include<iostream>
using namespace std;
const int N=1E5+10;
int a[N],q[N],h,t; //q存的是当前窗口中最值的下标
int main(){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
//窗口最小值
h=0,t=-1;
for(int i=0;i<n;i++){
//判断队头是否滑出窗口
if(h<=t && q[h]<i-k+1) h++;
while(h<=t && a[q[t]]>=a[i]) t--;
q[++t]=i;
if(i-k+1>=0) cout<<q[t]<<" ";
}
cout<<endl;
//窗口最大值
h=0,t=-1;
for(int i=0;i<n;i++){
//判断队头是否滑出窗口
if(h<=t && q[h]<i-k+1) h++;
while(h<=t && a[q[t]]<=a[i]) t--;
q[++t]=i;
if(i-k+1>=0) cout<<q[t]<<" ";
}
return 0;
}