栈
栈的特点
先进后出,和一个半封闭容器类似,放了一堆肉饼,先放的肉饼后倒出来
stk[n]数组代表栈,tt代表栈点
关于栈的插入
void add(int x)//插入元素
{
stk[++t] = x;
}
关于栈的删除
void del( )//删除元素,即弹出一个肉饼
{
tt--;
}
关于判断栈是否为空
bool stkempty()//判断栈是否为空
{
if (tt > 0) return false;
else return true;
}
总实现代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 10010;
int stk[N], tt;//stk表示栈,tt表示栈点下标
void add(int x)//插入元素
{
stk[++t] = x;
}
void del( )//删除元素,即弹出一个肉饼
{
tt--;
}
bool stkempty()//判断栈是否为空
{
if (tt > 0) return false;
else return true;
}
//栈顶 stk[tt]
int main()
{
return 0;
}
例题
问题描述
有一序列,输出每个数左边第一个比他小的数,没有则输出-1
诀窍:在while循环判断条件时,只要想该数不符合条件则跳过即可
//找出每个数左边离它最近的比它大/小的数
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 10010;
int stk[N], tt;
//暴力法
//void vio(int n)
//{
// for (int i = 0;i < n;;++i)//对每个数的列举
// {
// int j = 0;
// for (j = i -1;j >= 0;--j)
// {
// if (stk[i] > stk[j])
// {
// cout << stk[j]<<' ';
// break;
// }
// }
// if (j == -1) cout << -1 << ' ';
// }
//}
int main()
{
int n;
scanf("%d ", &n);
//单调栈法
for (int i = 0;i < n;++i)
{
int x;
scanf("%d ", &x);
while (tt && stk[tt] >= x) tt--;
if (tt) printf("%d\n", stk[tt]);
else printf("-1\n");
stk[++tt] = x;
}
}
队列
队列的特点
先进先出,和枪上膛相似,先插进去的子弹先打出来
q[N]表示队列,hh表示对头,tt表示队尾
关于队列的插入
void add(int x)//队尾插入元素
{
q[++tt] = x;
}
关于队列的删除(弹出)
void del( )//在队头弹出元素
{
hh++;
}
关于队列的判断是否为空
bool qempty()//判断是否为空
{
if (hh <= tt) return false;
else return true;
}
总实现代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 10010;
int q[N], hh, tt = -1;//hh表示队头,tt表示队尾
void add(int x)//队尾插入元素
{
q[++tt] = x;
}
void del( )//在对头弹出元素
{
hh++;
}
bool qempty()//判断是否为空
{
if (hh <= tt) return false;
else return true;
}
//对头元素q[hh],队尾元素q[tt]
int main()
{
return 0;
}
例题
//求出一定序列中,滑动窗口里的最小值和最大值
//第一行输出最小值
//第二行输出最大值
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
const int N = 1000010;
int a[N],q[N],hh,tt;
int main()
{
int n,k;
scanf("%d %d", &n,&k);
hh = 0, tt = -1;
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
for (int i = 0;i < n;++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]]);
}
cout << endl;
hh = 0, tt = -1;
for (int i = 0;i < n;++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]]);
}
cout << endl;
return 0;
}