Queue, Deque & PriorityQueue

FIFO, LIFO, priority — algorithm-এর মেরুদণ্ড

Read: ~40 min Advanced 5 practice problems Live code runner

1. Why Queues Matter

Many algorithms are a loop around a data structure. Change the data structure and you change the algorithm: a Queue gives BFS; a Stack (or LIFO Deque) gives DFS; a PriorityQueue gives Dijkstra, A*, and Huffman coding. Java exposes all three as distinct interfaces.

অনেক algorithm আসলে একটি data structure-এর চারপাশে loop। Data structure বদলালে algorithm বদলে যায় — Queue হলে BFS, Stack হলে DFS, PriorityQueue হলে Dijkstra/A*। Java তিনটিই আলাদা interface হিসেবে দেয়।

2. Queue — FIFO

A Queue<T> adds at one end and removes from the other — First-In, First-Out. Use ArrayDeque as a general-purpose Queue; it is faster than LinkedList.

Queue<T> এক প্রান্তে add, অন্য প্রান্তে remove — FIFO। General-purpose Queue হিসেবে ArrayDeque ব্যবহার করুন, এটি LinkedList-এর চেয়ে দ্রুত।
Main.java
import java.util.*;

class Main {
    public static void main(String[] args) {
        Queue<String> q = new ArrayDeque<>();
        q.offer("A");
        q.offer("B");
        q.offer("C");

        System.out.println("peek (front) = " + q.peek());
        while (!q.isEmpty()) {
            System.out.println("poll -> " + q.poll());
        }
    }
}
offer vs add, poll vs remove: the offer/poll/peek family returns false/null on capacity/empty; the add/remove/element family throws. Prefer the first family in modern Java.

offer/poll/peek ব্যর্থ হলে false/null দেয়; add/remove/element exception ছোঁড়ে। সাধারণত প্রথম family-ই ব্যবহার করবেন।

3. Deque — Both Ends

A Deque (double-ended queue) lets you add and remove at both ends in O(1). That makes it a Queue and a Stack in one class. Java recommends ArrayDeque over the legacy Stack class.

Deque দুই প্রান্তেই O(1)-এ add/remove — একই ক্লাসে Queue ও Stack দুইই। Modern Java-তে পুরনো Stack-এর বদলে ArrayDeque ব্যবহার করুন।
Deque — both ends support O(1) add/remove A B C D E addFirst↔removeFirst addLast↔removeLast Both ends · O(1) · preferred over Stack / LinkedList Figure 26.1 — Deque উভয় প্রান্তেই O(1); Stack ও Queue উভয়ের কাজ দেয়।
Main.java
import java.util.*;

class Main {
    public static void main(String[] args) {
        Deque<Integer> d = new ArrayDeque<>();
        d.addLast(10);
        d.addLast(20);
        d.addFirst(5);
        d.addLast(30);

        System.out.println("deque: " + d);
        System.out.println("first = " + d.peekFirst());
        System.out.println("last  = " + d.peekLast());

        // Use as a stack (LIFO)
        Deque<String> stack = new ArrayDeque<>();
        stack.push("A"); stack.push("B"); stack.push("C");
        System.out.println("pop -> " + stack.pop());
        System.out.println("stack: " + stack);
    }
}

4. PriorityQueue — Min-Heap by Default

PriorityQueue is a binary min-heap. poll() always returns the smallest element. To get a max-heap, pass a reversed Comparator.

PriorityQueue একটি binary min-heap। poll() সব সময় সবচেয়ে ছোট উপাদানটিই ফেরত দেয়। Max-heap দরকার হলে reversed Comparator দিন।
Main.java
import java.util.*;

class Main {
    public static void main(String[] args) {
        // Min-heap
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        pq.addAll(List.of(7, 2, 9, 1, 5, 3));
        while (!pq.isEmpty()) System.out.print(pq.poll() + " ");
        System.out.println();

        // Max-heap via reversed comparator
        PriorityQueue<Integer> max = new PriorityQueue<>(Comparator.reverseOrder());
        max.addAll(List.of(7, 2, 9, 1, 5, 3));
        while (!max.isEmpty()) System.out.print(max.poll() + " ");
        System.out.println();
    }
}

5. Custom Comparator + Real Example

For your own objects, supply a Comparator. Here we schedule tasks by priority (smaller = more urgent). We also show a textbook BFS over a tiny graph.

নিজের object-এর জন্য Comparator দিতে হবে। নিচে task scheduler (কম-priority = বেশি জরুরি) ও ছোট graph-এ BFS দেখানো হলো।
Main.java
import java.util.*;

class Main {
    record Task(String name, int priority) {}

    public static void main(String[] args) {
        PriorityQueue<Task> jobs = new PriorityQueue<>(
            Comparator.comparingInt(Task::priority)
        );
        jobs.offer(new Task("Send OTP", 1));
        jobs.offer(new Task("Nightly report", 9));
        jobs.offer(new Task("Fraud alert", 0));
        jobs.offer(new Task("Welcome email", 5));

        while (!jobs.isEmpty()) {
            Task t = jobs.poll();
            System.out.printf("run [p=%d] %s%n", t.priority(), t.name());
        }

        // --- BFS over a small graph ---
        Map<String, List<String>> g = new HashMap<>();
        g.put("A", List.of("B", "C"));
        g.put("B", List.of("D"));
        g.put("C", List.of("D", "E"));
        g.put("D", List.of());
        g.put("E", List.of());

        Queue<String> q = new ArrayDeque<>();
        Set<String> seen = new HashSet<>();
        q.offer("A"); seen.add("A");
        while (!q.isEmpty()) {
            String v = q.poll();
            System.out.print("visit " + v + " ");
            for (String n : g.get(v)) {
                if (seen.add(n)) q.offer(n);
            }
        }
        System.out.println();
    }
}

6. Vocabulary & Complexity

OpArrayDequePriorityQueueবাংলায়
offer / addO(1)O(log n)PQ-এ heapify cost।
poll / removeO(1)O(log n)PQ-এ sift-down।
peekO(1)O(1)দুটিই দ্রুত।
containsO(n)O(n)Heap/list-এ linear search।
OrderingInsertionPriority (heap)Deque-এ insertion; PQ-তে priority।
Gotcha: iterating a PriorityQueue with a for-each loop does not give sorted order — only poll() does. The heap is just partially ordered.

for-each দিয়ে PriorityQueue iterate করলে sorted order পাবেন না — শুধু poll()-ই sorted order দেয়। Heap আংশিকভাবেই order-এ থাকে।

7. Practice Problems

  1. Implement a simple FIFO queue of 5 events and drain it.
    ৫টি event-এর FIFO queue তৈরি ও ধারাবাহিকভাবে poll করুন।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Main {
        public static void main(String[] args) {
            Queue<String> q = new ArrayDeque<>();
            for (int i = 1; i <= 5; i++) q.offer("event-" + i);
            while (!q.isEmpty()) System.out.println(q.poll());
        }
    }
  2. Use ArrayDeque as a stack to reverse a string.
    ArrayDeque-কে stack হিসেবে ব্যবহার করে একটি string উল্টে ফেলুন।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Main {
        public static void main(String[] args) {
            String s = "Bangladesh";
            Deque<Character> st = new ArrayDeque<>();
            for (char c : s.toCharArray()) st.push(c);
            StringBuilder sb = new StringBuilder();
            while (!st.isEmpty()) sb.append(st.pop());
            System.out.println(sb);
        }
    }
  3. Use a PriorityQueue to find the three smallest numbers in {9,3,7,1,5,8,2}.
    PriorityQueue দিয়ে {9,3,7,1,5,8,2}-এর তিনটি ক্ষুদ্রতম সংখ্যা বের করুন।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Main {
        public static void main(String[] args) {
            PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(9, 3, 7, 1, 5, 8, 2));
            for (int i = 0; i < 3; i++) System.out.println(pq.poll());
        }
    }
  4. Why is ArrayDeque preferred over Stack in modern Java?
    আধুনিক Java-তে Stack-এর বদলে ArrayDeque কেন?
    ✨ Show Answer

    Answer: java.util.Stack extends Vector, which synchronizes every method. That is slow, and in single-threaded code (the common case) it's pure overhead. ArrayDeque is unsynchronized, cache-friendly, and usually several times faster. Also, Stack's API is a mix of queue and stack semantics, which confuses readers. Prefer Deque<T> s = new ArrayDeque<>(); and use push/pop/peek.

    Stack Vector-থেকে inherit করা, প্রতিটি method synchronized — ফলে single-thread code-এ শুধু overhead। ArrayDeque unsynchronized, cache-friendly, সাধারণত বেশ কয়েক গুণ দ্রুত। push/pop/peek দিয়ে তাকেই stack হিসেবে ব্যবহার করা উত্তম।

  5. Schedule 4 tasks by priority using a PriorityQueue and Comparator.comparingInt.
    PriorityQueue ও Comparator.comparingInt দিয়ে ৪টি task priority-অনুযায়ী চালান।
    ✨ Show Answer
    Main.java
    import java.util.*;
    class Main {
        record Job(String name, int prio) {}
        public static void main(String[] args) {
            PriorityQueue<Job> q = new PriorityQueue<>(Comparator.comparingInt(Job::prio));
            q.offer(new Job("build", 3));
            q.offer(new Job("hotfix", 0));
            q.offer(new Job("docs", 7));
            q.offer(new Job("tests", 2));
            while (!q.isEmpty()) System.out.println(q.poll());
        }
    }

Summary — Module 26

Queue is FIFO, Deque is both-ended, PriorityQueue is a min-heap. Use ArrayDeque for every day needs — Queue, Stack, Deque — and reserve PriorityQueue for priority-based workflows like schedulers, Dijkstra, and Huffman. Mastering these unlocks classic BFS and greedy algorithms.

Queue FIFO, Deque দুই প্রান্তে, PriorityQueue min-heap। সাধারণ কাজে ArrayDeque (Queue/Stack/Deque তিন-ই চলে), priority-ভিত্তিক কাজে PriorityQueue। এগুলো শিখলেই BFS ও greedy algorithm দুটিই হাতের মুঠোয়।

Next Module → Phase 6 শুরু — Lambda Expressions ও Functional Interface।