单调队列

单调队列顾名思义,就是保持一定单调性的队列,他可以访问队头和队尾的元素,只能从队尾添加元素
假设队列的单调性为从队尾到队首单调递增,要保持队列的单调性,在向队尾添加元素时,需要比较队尾元素和要添加的元素(假设为n)的大小关系:

  • 如果队尾元素大于n,那么将n添加到队尾
  • 如果队尾元素小于n,那么将队尾元素弹出,比较n和新的队尾元素的大小关系,循环直至队列为空或者n小于队尾元素为止,将n添加到队尾

那么,这样维护后的队列就是一个单调(递增)队列。

举个例子,将1, 2, 45, 33, 66, 22, 9,逐个添加到单调队列中,看一下最后的队列是什么样子:
单调队列 - 图1

可以见到,最后得到的队列从队尾到队头依次为9,22,66,满足单调递增
用C++来实现一个基于deque的单调队列,代码如下:

  1. class MyQueue
  2. {
  3. public:
  4. MyQueue() = default;
  5. //向队尾添加元素
  6. void push_back(int x)
  7. {
  8. // 要保持队列的单调性,需要判断队尾元素的大小
  9. // 如果队尾元素小于要添加的元素,将队尾元素弹出,循环直到队列为空或者队尾元素大于要添加的元素为止
  10. while (!dq.empty() && dq.back() < x) {
  11. dq.pop_back();
  12. }
  13. dq.push_back(x);
  14. }
  15. // 弹出队头元素
  16. void pop_front()
  17. {
  18. dq.pop_front();
  19. }
  20. // 访问队头元素
  21. int front()
  22. {
  23. return dq.front();
  24. }
  25. // 访问队尾元素
  26. int back()
  27. {
  28. return dq.back();
  29. }
  30. bool empty()
  31. {
  32. return dq.empty();
  33. }
  34. public:
  35. deque<int> dq;
  36. };
  37. void test01()
  38. {
  39. vector<int> v{1, 2, 45, 33, 66, 22, 9};
  40. MyQueue mq;
  41. for (auto n : v)
  42. {
  43. mq.push_back(n);
  44. }
  45. while (!mq.empty())
  46. {
  47. cout << mq.front() << endl;
  48. mq.pop_front();
  49. }
  50. }
  51. int main()
  52. {
  53. test01(); //输出结果为 66,22,9
  54. return 0;
  55. }