栈的特点

先进后出,和一个半封闭容器类似,放了一堆肉饼,先放的肉饼后倒出来

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;
}