数组模拟栈与队列(用C/C++实现)

一、栈            先进后出

  1. 插入元素 stk[ ++ tt] = x
  2. 弹出元素 tt –
  3. 判断栈是否为空 tt > 0不空 ,tt < 0空
  4. 栈顶 stk[ tt ]

二、队列         先进先出 队尾插入元素,队头弹出元素

  1. 插入元素 q[ ++ tt] = x
  2. 弹出元素 hh ++ –
  3. 判断栈是否为空 hh <= tt不空 ,hh > tt空
  4. 栈顶 q[ hh ]
#include<iostream>

using namespace std;

const int N = 100010;

int stk[N], tt;
//栈
 
//插入 
stk[ ++ tt] = x;

//弹出
tt --;

// 判断栈是否为空
if(tt > 0) not empty
else empty
//队列

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

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

//弹出
hh ++;

//判断队列是否为空
 if(hh <= tt) not empty
 else empty
 
 //取出队头元素
 q[hh] 

三、 单调栈(算法时间复杂度O(n))

用的比较多的题型:一列数,找到在它左侧最靠近它且比它小的数,若找到返回该数,找不到返回-1

将这一组数放入栈中,假设我们遍历到了a[y]这个元素之后,如果在a[y]之前存在a[x],a[x] >= a[y],那么我们永远不会选择a[x]了,故a[x]会被a[y]更新掉,即更新掉下降序列。不断更新之后,只剩下单调序列,故为单调栈。

#include<iostream>

using namespace std;

const int N = 100010;

int stk[N], tt;
//栈
 
//插入 
stk[ ++ tt] = x;

//弹出
tt --;

// 判断栈是否为空
if(tt > 0) not empty
else empty
//队列

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

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

//弹出
hh ++;

//判断队列是否为空
 if(hh <= tt) not empty
 else empty
 
 //取出队头元素
 q[hh] 

四、 单调队列

常用:求滑动窗口里面的最小(大)值

我们使用一个队列来维护窗口,在这个队列中,靠左的元素如果更大(小),则我们就不可能会将它输出,即被更新掉,更新完后队列中的最小值即为队头。

#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++)
	{
		//判断队头是否已经滑出窗口
		//队伍终点是i,起点是i - k + 1,起点的下标已经在队头的右侧,则队列移动一位 
		if(hh <= tt && i - k + 1 > q[hh]) hh++;
		//筛选队列中靠左且比当前元素大的值 
		while(hh <= tt && a[q[tt]] >= a[i]) tt --; 
		q[ ++ tt] = i;//先把i插入,i有可能是最小值 
		//不足k个时,输出队头 
		if(i >= k - 1) printf("%d ", a[q[hh]]); 
		
	}
	
	puts("");
	//最大值 
	hh = 0, tt = -1;
	for(int i = 0; i < n; i++)
	{
		//判断队头是否已经滑出窗口
		//队伍终点是i,起点是i - k + 1,起点的下标已经在队头的右侧,则队列移动一位 
		if(hh <= tt && i - k + 1 > q[hh]) hh++;
		//筛选队列中靠左且比当前元素大的值 
		while(hh <= tt && a[q[tt]] <= a[i]) tt --; 
		q[ ++ tt] = i;//先把i插入,i有可能是最小值 
		//不足k个时,输出队头 
		if(i >= k - 1) printf("%d ", a[q[hh]]); 
		
	}
	
	puts("");
	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值