单调队列

单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。


以单调不减队列为例:队列内的元素(e1,e2,e3...en)存在(e1<=e2<=e3<=...<=en)的关系,所以队首元素e1一定是最小的元素。与优先队列不同的是,当有一个新的元素e入队时,先要将队尾的所有大于e的元素弹出,以保证单调性,再让元素e入队尾。


例如这样一组数(1,3,2,1,5,6),进入单调不减队列的过程如下:

1入队,得到队列(1);

3入队,得到队列(1,3);

2入队,这时,队尾的的元素3>2,将3从队尾弹出,新的队尾元素1<2,不用弹出,将2入队,得到队列(1,2);

1入队,2>1,将2从队尾弹出,得到队列(1,1);

5入队,得到队列(1,1,5);

6入队,得到队列(1,1,5,6);


代码实现:

#include <iostream>

using namespace std;

class MonotonicQueue
{

#define MAXN 1000000

public:
	MonotonicQueue(void)
	{
		q = new int[MAXN+5];
		f = r = 0;
	}
	void push(const int val)
	{
		while (r > f && q[r-1] > val)	//弹出大于新元素的队尾元素
		{
			r--;
		}
		q[r++] = val;
	}
	int front(void)
	{
		if (f < r)
		{
			return q[f];
		}
		return 0;
	}
	void pop_front(void)
	{
		if (f < r)
		{
			f++;
		}
	}
	bool isEmpty(void)
	{
		return f == r;
	}
	void clear(void)
	{
		f = r = 0;
	}
	~MonotonicQueue(void)
	{
		delete q;
	}
private:
	int *q;
	int f;
	int r;
};

int main(void)
{
	MonotonicQueue mq;
	int n;
	while (cin >> n)
	{
		int i;
		for (i = 0; i < n; i++)
		{
			int a;
			cin >> a;
			mq.push(a);
		}

		while (!mq.isEmpty())
		{
			cout << mq.front() << endl;
			mq.pop_front();
		}
		mq.clear();
	}
	return 0;
}
访问队首和删除队首元素的时间复杂度为O(1),在队尾加入元素的最坏情况下的时间复杂度为O(n),n为队列当前长度。所以,可以采用二分查找,来确定新加入元素应该插入的位置。

你可能感兴趣的:(单调队列)