Queues, Deques & Priority Queues (Intro)
Queue, Deque ও Priority Queue
1. FIFO — First In, First Out
A queue is the opposite of a stack: the first one in is the first one out.
Operations: enqueue / push at the back, dequeue / pop at the front, front() peek.
Queues power BFS, schedulers, message buses, print spoolers — anything where order of arrival matters.
2. Circular Queue Over a Fixed Array
A naive linear queue wastes space — once you dequeue from the front, the empty slot is gone.
A circular queue wraps the rear pointer back around using (rear + 1) % capacity,
so all slots stay usable.
#include <bits/stdc++.h>
using namespace std;
struct CQ {
vector<int> a;
int front, rear, sz, cap;
CQ(int n) : a(n), front(0), rear(-1), sz(0), cap(n) {}
bool push(int x) {
if (sz == cap) return false;
rear = (rear + 1) % cap;
a[rear] = x; sz++;
return true;
}
bool pop() {
if (sz == 0) return false;
front = (front + 1) % cap; sz--;
return true;
}
int peek() { return a[front]; }
};
int main() {
CQ q(4);
q.push(10); q.push(20); q.push(30); q.push(40);
cout << "front=" << q.peek() << "\n";
q.pop(); q.pop();
q.push(50); q.push(60); // wraps around
cout << "after wrap, front=" << q.peek() << ", size=" << q.sz;
}
3. Deque — Push and Pop at Both Ends
A deque (double-ended queue) is a queue that supports O(1) operations at both ends.
std::deque<T> in C++ is the standard implementation.
The killer use is the sliding-window maximum in O(n).
উইন্ডোতে decreasing order-এ index রাখুন — front-ই উত্তর।
#include <bits/stdc++.h>
using namespace std;
vector<int> windowMax(vector<int>& a, int k) {
deque<int> dq; // stores indices, decreasing values
vector<int> ans;
for (int i = 0; i < (int)a.size(); i++) {
while (!dq.empty() && dq.front() <= i - k) dq.pop_front();
while (!dq.empty() && a[dq.back()] < a[i]) dq.pop_back();
dq.push_back(i);
if (i >= k - 1) ans.push_back(a[dq.front()]);
}
return ans;
}
int main() {
vector<int> a = {1,3,-1,-3,5,3,6,7};
for (int x : windowMax(a, 3)) cout << x << " ";
}
Each index is pushed and popped at most once → O(n) total.
4. Priority Queue — A Quick Preview
A priority queue is a queue where highest priority (max or min) comes out first,
not just FIFO. The standard implementation is a binary heap (Module 15).
std::priority_queue<T> is a max-heap by default.
Queue / Deque
- FIFO order or both-ends
- O(1) for all operations
- Used in: BFS, sliding window, scheduling
Priority Queue
- Highest-priority first
- O(log n) push / pop, O(1) top
- Used in: Dijkstra, Huffman, top-K problems
5. Practice Problems
-
Implement a queue using two stacks (amortised O(1)).দুটি stack দিয়ে queue বানান (amortised O(1))।
✨ Show Answer (উত্তর দেখুন)
a1.cpp#include <bits/stdc++.h> using namespace std; struct QQ { stack<int> in, out; void push(int x) { in.push(x); } int pop() { if (out.empty()) while (!in.empty()) { out.push(in.top()); in.pop(); } int v = out.top(); out.pop(); return v; } }; int main() { QQ q; for (int x : {1,2,3}) q.push(x); cout << q.pop() << " " << q.pop() << " " << q.pop(); } -
Print the first negative integer in every window of size k.প্রতিটি size-k window-এ প্রথম negative integer প্রিন্ট করুন।
✨ Show Answer (উত্তর দেখুন)
a2.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {12,-1,-7,8,-15,30,16,28}; int k = 3; deque<int> dq; for (int i = 0; i < (int)a.size(); i++) { if (a[i] < 0) dq.push_back(i); while (!dq.empty() && dq.front() <= i - k) dq.pop_front(); if (i >= k - 1) cout << (dq.empty() ? 0 : a[dq.front()]) << " "; } } -
Rotten oranges (BFS). Given a grid of fresh (1) and rotten (2) oranges, return the minutes until all rot.Rotten oranges সমস্যা — BFS দিয়ে।
✨ Show Answer (উত্তর দেখুন)
a3.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<vector<int>> g = {{2,1,1},{1,1,0},{0,1,1}}; int R = g.size(), C = g[0].size(), fresh = 0, t = 0; queue<pair<int,int>> q; for (int i=0; i<R; i++) for (int j=0; j<C; j++) { if (g[i][j]==2) q.push({i,j}); if (g[i][j]==1) fresh++; } int dx[]={-1,1,0,0}, dy[]={0,0,-1,1}; while (!q.empty() && fresh) { int sz = q.size(); while (sz--) { auto [x,y] = q.front(); q.pop(); for (int d=0; d<4; d++) { int nx=x+dx[d], ny=y+dy[d]; if (nx>=0&&nx<R&&ny>=0&&ny<C&&g[nx][ny]==1) { g[nx][ny]=2; fresh--; q.push({nx,ny}); } } } t++; } cout << (fresh ? -1 : t); } -
Use a min-priority-queue to merge k sorted arrays into one.Min-PQ দিয়ে k সর্টেড অ্যারে merge করুন।
✨ Show Answer (উত্তর দেখুন)
a4.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<vector<int>> arrs = {{1,5,9},{2,6},{3,4,10}}; priority_queue<tuple<int,int,int>, vector<tuple<int,int,int>>, greater<>> pq; for (int i=0; i<(int)arrs.size(); i++) if (!arrs[i].empty()) pq.push({arrs[i][0], i, 0}); while (!pq.empty()) { auto [v, i, j] = pq.top(); pq.pop(); cout << v << " "; if (j+1 < (int)arrs[i].size()) pq.push({arrs[i][j+1], i, j+1}); } } -
Reorganize a string so no two adjacent characters are the same (use a max-PQ on counts).পাশাপাশি একই char না হয় — string reorganize করুন।
✨ Show Answer (উত্তর দেখুন)
a5.cpp#include <bits/stdc++.h> using namespace std; int main() { string s = "aaabbc"; int cnt[26] = {}; for (char c : s) cnt[c-'a']++; priority_queue<pair<int,char>> pq; for (int i=0; i<26; i++) if (cnt[i]) pq.push({cnt[i], 'a'+i}); string out; while (pq.size() >= 2) { auto [c1, ch1] = pq.top(); pq.pop(); auto [c2, ch2] = pq.top(); pq.pop(); out += ch1; out += ch2; if (--c1) pq.push({c1, ch1}); if (--c2) pq.push({c2, ch2}); } if (!pq.empty()) { if (pq.top().first > 1) { cout << "impossible"; return 0; } out += pq.top().second; } cout << out; } -
Implement a stack using two queues (amortised).দুটি queue দিয়ে stack বানান।
✨ Show Answer (উত্তর দেখুন)
a6.cpp#include <bits/stdc++.h> using namespace std; struct SS { queue<int> q; void push(int x) { q.push(x); int sz = q.size(); while (--sz) { q.push(q.front()); q.pop(); } } int pop() { int v = q.front(); q.pop(); return v; } }; int main() { SS s; for (int x : {1,2,3}) s.push(x); cout << s.pop() << " " << s.pop() << " " << s.pop(); } -
Find the top-k frequent integers using a min-heap of size k.size-k min-heap দিয়ে top-k frequent integer বের করুন।
✨ Show Answer (উত্তর দেখুন)
a7.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {1,1,1,2,2,3,4,4,4,4}; int k = 2; unordered_map<int,int> cnt; for (int x : a) cnt[x]++; priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq; for (auto& [v, c] : cnt) { pq.push({c, v}); if ((int)pq.size() > k) pq.pop(); } while (!pq.empty()) { cout << pq.top().second << " "; pq.pop(); } }
Summary — Module 10
FIFO queues, double-ended deques, and priority queues round out the linear toolbox. BFS needs a queue. Sliding-window max needs a deque. Dijkstra needs a priority queue. Phase 2 is complete — next we sort and search.