数组模拟队列以及单调队列

队列的定义 

queue是STL容器中的一种,队列有队头和队尾,队列可以从两头弹出元素

 

#include <iostream>
#include <queue>

using namespace std;

int main()
{
	//队列queue
	//push/pop/front/back/empty
	//push
	queue<int> a;
    for (int i = 0; i < 5; i ++)
    {
		a.push(i);//从队尾插入
	}
	//front/back
	cout << a.front() << endl;//返回队头元素
	cout << a.back() << endl;//返回队尾元素
	a.pop();//把队头拿掉
	cout << a.front() << endl;
	a.pop();
	cout << a.front() << endl;
	
	cout << "清空一个数组:"<<endl;
	queue<int> b;
	for (int i = 0; i < 5 ; i ++)
	{
		b.push(i);
	} 
	for (int i = 0; i < 5; i ++)
	{
		b.pop();
	}
	//empty
	cout << b.empty() << endl;
	//队列是无序的
	queue<int> c;
	c.push(9);
	c.push(1);
	c.push(2);
	cout << c.front() << endl;
	
	//队列里面装结构体
	cout << "队列里面装结构体:" << endl;
	//定义一个结构体
	struct res
	{
		int x, y;
		bool operator < (const res& t) const//结构体内必须定义小于号
		{
			return x < t.x;
		}
	};
	queue<res> d;//定义一个结构体的队列
	res p;
	p.x = 1;
	p.y = 2;
	d.push(p);//将p这个结构体插到d这个队列中去
	res q;
	q.x = 4;
	q.y = 3;
	d.push(q);//将q这个结构体插入到d这个队列中去
	
	cout << d.front().x << ' ' << d.front().y << endl;//输出队头
	cout << d.back().x << ' ' << d.back().y << endl;//输出队尾
	d.pop();//将队头删掉
	cout << d.front().x << ' ' << d.front().y << endl;
	cout << endl;
	
	
	//优先队列priority_queue(大根堆)
	priority_queue<int> m;//大根堆,堆顶为大根
	//push/pop/top
	//push
	m.push(5);
	m.push(1);
	m.push(6);
	m.push(2);
	//top
	cout << m.top() << endl;//输出最大值
	//pop
    m.pop();//删除堆顶
    cout << m.top() << endl;
    //大根堆里装结构体
    struct ans
    {
		int v, w;
		bool operator < (const ans& t) const //大根堆定义小于号
		{
			return v < t.v;
		}
	};
	priority_queue<ans> n;
	ans a1;
	a1.v = 2;
	a1.w = 1;
	ans a2;
	a2.v = 2;
	a2.w = 0;
	n.push(a1);
	n.push(a2);
	//先比较v,谁大谁堆顶
	//v相同比较w,谁大谁堆顶
	cout << n.top().v << ' ' << n.top().w << endl;
	n.pop();//删除堆顶
	cout << n.top().v << ' ' << n.top().w << endl;
	cout << endl;
	
	
	//优先队列priority_queue<int,vector<int>,greater<int>>(小根堆)
	//push/top/pop
	priority_queue<int, vector<int>, greater<int>> s;
	//push
	s.push(5);
	s.push(1);
	//top
	cout << s.top() << endl;
	//小根堆里装结构体
	struct sum
	{
		int t1, t2;
		bool operator > (const sum& t) const //小根堆定义大于号
		{
			return t1 > t.t1;
		}
	};
	priority_queue<sum, vector<sum>, greater<sum>> k;
	sum s1;
	s1.t1 = 1;
	s1.t2 = 5;
	sum s2;
	s2.t1 = 0;
	s2.t2 = 9;
	k.push(s1);
	k.push(s2);
	cout << k.top().t1 << ' ' << k.top().t2 << endl;
	//pop
	k.pop();
	cout << k.top().t1 << ' ' << k.top().t2 << endl;	
}

 

AcWing 829. 模拟队列

 输入样例:

10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6

代码展示: 

#include <iostream>

using namespace std;

const int N = 100010;
int q[N], hh = 0, tt = -1;//初始化队头队尾
int main()
{
    cin.tie(0);
    int m;
    cin >> m;
    
    while (m --)
    {
        string op;
        cin >> op;
        int x;
        if (op == "push") cin >> x, q[++ tt] = x;//从队尾插入
        if (op == "pop") hh ++;//队头弹出一个元素
        if (op == "query") cout << q[hh] <<endl;
        if (op == "empty") //判断队列是否为空
        {
            if (hh > tt) cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    }
    return 0; 
}

AcWing 154. 滑动窗口

输入样例: 

8 3
1 3 -1 -3 5 3 6 7

q[]存储的是坐标(注意!!!)

a[]存储元素

hh为队头,tt为队尾

代码展示: 

#include <iostream>

using namespace std;

const int N = 1000100;
int a[N], q[N], hh = 0, tt = -1;
int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i ++ ) scanf("%d",&a[i]);
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - q[hh] + 1 > k) hh ++;
//当队列中所存储的下标大于k时,就将队头弹出
        while (a[i] < a[q[tt]] && hh <= tt) tt --;
//当前插入的元素比队尾所指向的元素小的话,将队尾弹出
//队列中保持单调上升的趋势,不满足的,就把弹出
        q[++ tt] = i;
        if (i >= k - 1) printf ("%d ", a[q[hh]]);
//队列里面是单调递增的,最小的在队头,所以输出队头
//每次输出队头
    }
    puts("");
    hh = 0, tt = -1;
//与上面类似
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - q[hh] + 1 > k) hh ++;
        while (hh <= tt && a[i] > a[q[tt]]) tt --;
        q[++ tt] = i;
        if (i >= k - 1) printf ("%d ",a[q[hh]]);
    }
}

 思路+解析:

以所给数据为例模拟窗口移动过程:

 

 

 接下来是模拟队列变化过程(以最小值为例):

 维持队列里面存储的下标所对应的元素的值是单调递增的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值