PriorityQueue ve ArrayDeque
Bazı problemler "sıradaki elemanı" özel bir kurala göre ister: ya uçlardan (baş/son) erişim (yığın, kuyruk) ya da önceliğe göre erişim. Java bu iki ihtiyaca iki güçlü sınıfla yanıt verir: çift uçlu kuyruk ArrayDeque v…
PriorityQueue ve ArrayDeque
Bazı problemler "sıradaki elemanı" özel bir kurala göre ister: ya uçlardan (baş/son) erişim
(yığın, kuyruk) ya da önceliğe göre erişim. Java bu iki ihtiyaca iki güçlü sınıfla yanıt verir:
çift uçlu kuyruk ArrayDeque ve öncelik kuyruğu PriorityQueue. İkisi de Queue arayüzünü
uygular ama tamamen farklı işler için tasarlanmıştır.
ArrayDeque: yığın ve kuyruk
ArrayDeque (array deque = çift uçlu kuyruk), her iki uçtan da O(1) ekleme/çıkarma yapar. Tek
sınıfla hem yığın hem kuyruk kurarsın:
// Yığın (LIFO) — son giren ilk çıkar deque.push(x); deque.pop(); deque.peek(); // Kuyruk (FIFO) — ilk giren ilk çıkar deque.offer(x); deque.poll(); deque.peek(); // Çift uçlu deque.addFirst(x); deque.addLast(x); deque.peekFirst(); deque.peekLast();
Örnek 1 (./Ornek1.java) ArrayDeque'i yığın, kuyruk ve çift uçlu olarak kullanır.
Neden
ArrayDeque?
- Yığın için: Eski
StacksınıfıVectortabanlıdır (senkronize, yavaş, eski). Modern Java'da yığın gerekiyorsaArrayDequeönerilir.- Kuyruk için:
LinkedListdeQueue'dur amaArrayDequedaha hızlı ve az bellek kullanır (dizi tabanlı, önbellek dostu).- Dikkat:
nulleleman kabul etmez (null, "eleman yok" sinyaliyle karışmasın diye).
PriorityQueue: öncelik kuyruğu
PriorityQueue, elemanları ekleme sırasına göre değil, önceliğe göre verir. İçte bir
heap (yığın ağacı) tutar; peek/poll her zaman en öncelikli elemanı döndürür:
PriorityQueue<Integer> pq = new PriorityQueue<>(); // min-heap (en küçük önce) PriorityQueue<Integer> max = new PriorityQueue<>(Comparator.reverseOrder()); // max-heap PriorityQueue<Gorev> sch = new PriorityQueue<>(Comparator.comparingInt(Gorev::oncelik));
Maliyetler: add/poll O(log n), peek O(1). Örnek 2 (./Ornek2.java) min-heap, max-heap ve
gerçek bir görev zamanlayıcı (en acil iş önce) gösterir.
Kullanım alanları: görev/iş zamanlama, Dijkstra/A* gibi graf algoritmaları, "en yakın/en büyük K eleman" problemleri, olay simülasyonu.
Önemli:
PriorityQueue'yufor-each/iterator ile gezmek sıralı sonuç vermez — sıra yalnızcapollile birer birer çıkarınca ortaya çıkar. Tümünü sıralı istiyorsan ya hepsinipollet ya da bir listeye alıpsortuygula.
Karşılaştırma
| Sınıf | Erişim kuralı | Tipik kullanım |
|---|---|---|
ArrayDeque (yığın) | LIFO (son giren ilk çıkar) | Geri-al, ifade ayrıştırma, DFS |
ArrayDeque (kuyruk) | FIFO (ilk giren ilk çıkar) | İş kuyruğu, BFS |
PriorityQueue | Önceliğe göre | Zamanlayıcı, Dijkstra, top-K |
Özet
İki uç-erişim koleksiyonunu öğrendik: her iki uçtan hızlı erişen ve modern yığın/kuyruk seçimi olan ArrayDeque (Örnek 1) ile elemanları önceliğe göre veren heap tabanlı PriorityQueue (Örnek 2). "Yığın/kuyruk → ArrayDeque, önceliğe göre → PriorityQueue" kuralını benimse. Sırada, metni verimli biçimde inşa etmenin yolu: StringBuilder.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: ArrayDeque — hem yığın (stack) hem kuyruk (queue) için hızlı çift uçlu yapı.
2// Çalıştırma: java Ornek1.java
3import java.util.ArrayDeque;
4import java.util.Deque;
5
6public class Ornek1 {
7
8 public static void main(String[] args) {
9 // YIĞIN (LIFO) olarak: push/pop/peek. (Eski Stack sınıfının yerine ÖNERİLEN.)
10 Deque<String> yigin = new ArrayDeque<>();
11 yigin.push("sayfa1"); yigin.push("sayfa2"); yigin.push("sayfa3");
12 System.out.println("Yığın: " + yigin);
13 System.out.println("pop (geri): " + yigin.pop() + " -> " + yigin); // son giren ilk çıkar
14 System.out.println("peek (tepe): " + yigin.peek());
15
16 // KUYRUK (FIFO) olarak: offer/poll/peek.
17 Deque<String> kuyruk = new ArrayDeque<>();
18 kuyruk.offer("müşteri1"); kuyruk.offer("müşteri2"); kuyruk.offer("müşteri3");
19 System.out.println("\nKuyruk: " + kuyruk);
20 System.out.println("poll (ilk): " + kuyruk.poll() + " -> " + kuyruk); // ilk giren ilk çıkar
21
22 // ÇİFT UÇLU: iki uçtan da ekle/çıkar.
23 Deque<Integer> deque = new ArrayDeque<>();
24 deque.addFirst(1); deque.addLast(2); deque.addFirst(0);
25 System.out.println("\nDeque (çift uçlu): " + deque);
26 System.out.println("ilk=" + deque.peekFirst() + ", son=" + deque.peekLast());
27
28 System.out.println("""
29
30 --- ArrayDeque ---
31 Çift uçlu kuyruk (double-ended queue): her iki uçtan ekle/çıkar O(1).
32 Yığın olarak: push/pop/peek (LIFO). Kuyruk olarak: offer/poll/peek (FIFO).
33 NEDEN ArrayDeque? Eski Stack (Vector tabanlı, senkronize, yavaş) yerine ÖNERİLİR;
34 LinkedList'e göre de daha hızlı ve az bellek kullanır. null eleman KABUL ETMEZ.""");
35 }
36}Ornek2
çalıştırılabilir1// Ornek2: PriorityQueue — öncelik kuyruğu (heap). En öncelikli eleman önce çıkar.
2// Çalıştırma: java Ornek2.java
3import java.util.Comparator;
4import java.util.PriorityQueue;
5
6public class Ornek2 {
7
8 record Gorev(String ad, int oncelik) {}
9
10 public static void main(String[] args) {
11 // Varsayılan: min-heap (en KÜÇÜK önce çıkar).
12 PriorityQueue<Integer> minHeap = new PriorityQueue<>();
13 minHeap.add(50); minHeap.add(10); minHeap.add(30); minHeap.add(20);
14 System.out.print("Min-heap çıkış sırası: ");
15 while (!minHeap.isEmpty()) System.out.print(minHeap.poll() + " "); // 10 20 30 50
16 System.out.println();
17
18 // Max-heap: Comparator ile ters (en BÜYÜK önce).
19 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
20 maxHeap.addAll(java.util.List.of(50, 10, 30, 20));
21 System.out.print("Max-heap çıkış sırası: ");
22 while (!maxHeap.isEmpty()) System.out.print(maxHeap.poll() + " "); // 50 30 20 10
23 System.out.println();
24
25 // Gerçek senaryo: görev zamanlayıcı — düşük 'oncelik' sayısı = daha acil.
26 PriorityQueue<Gorev> zamanlayici = new PriorityQueue<>(Comparator.comparingInt(Gorev::oncelik));
27 zamanlayici.add(new Gorev("e-posta gönder", 5));
28 zamanlayici.add(new Gorev("sistem çökmesi!", 1));
29 zamanlayici.add(new Gorev("rapor üret", 3));
30 System.out.println("\nGörevler önceliğe göre işleniyor:");
31 while (!zamanlayici.isEmpty()) {
32 Gorev g = zamanlayici.poll();
33 System.out.println(" [" + g.oncelik() + "] " + g.ad());
34 }
35
36 System.out.println("""
37
38 --- PriorityQueue (öncelik kuyruğu) ---
39 Elemanları öncelik sırasına göre verir (FIFO değil!). İçte 'heap' (yığın ağacı) kullanır.
40 add/offer O(log n), peek O(1), poll O(log n). peek/poll HER ZAMAN en öncelikliyi verir.
41 Varsayılan min-heap (en küçük); Comparator ile max-heap veya özel öncelik.
42 Kullanım: görev/iş zamanlama, Dijkstra/A* gibi algoritmalar, 'en yakın K eleman'.
43 NOT: kuyruğu gezmek (iterator) SIRALI değildir; sıra yalnızca poll ile ortaya çıkar.""");
44 }
45}