Queue (Antrean)
Terakhir diperbarui
Queue adalah struktur data dengan dua ujung yang aktif. Nilai baru masuk di belakang, dan nilai keluar dari depan, jadi yang menunggu paling lama dilayani lebih dulu. Itulah FIFO, dan persis seperti antrean di loket: masuk dari belakang dan dilayani dari depan membuat antreannya adil. Tekan Putar di atas dan lihat nilai masuk dari satu sisi lalu keluar dari sisi lainnya.
Karena setiap ujung dicatat oleh indeks atau pointer-nya sendiri, kedua operasi bernilai O(1) dan tidak ada yang menggeser data lainnya. Itulah sebabnya queue menjadi dasar segala sesuatu yang memproses pekerjaan sesuai urutan kedatangan: antrean cetak, antrean tugas dan pesan, buffer request, dan breadth-first search, yang mengunjungi graf level demi level justru karena menyimpan frontier-nya di dalam queue. Pindahkan ujung pengambilan ke belakang, dan kamu mendapatkan stack.
Kompleksitas waktu dan ruang
Untuk queue yang dibangun di atas ring buffer atau linked list, dua implementasi standarnya:
| Operasi | Kompleksitas | Catatan |
|---|---|---|
| Enqueue | O(1) | Tulis di belakang dan majukan indeks belakang. |
| Dequeue | O(1) | Baca di depan dan majukan indeks depan, tanpa pergeseran. |
| Peek (depan) | O(1) | Baca nilai terdepan tanpa mengeluarkannya. |
| Pencarian | O(n) | Bukan kegunaan queue: kamu harus mengosongkannya untuk melihat isinya. |
| Ruang | O(n) | Satu slot per nilai yang menunggu. |
Langkah demi langkah
| Langkah | Apa yang terjadi |
|---|---|
| 1 | Queue dimulai dalam keadaan kosong, dengan depan dan belakang menunjuk ke slot yang sama. |
| 2 | Enqueue menulis nilai di belakang, lalu memajukan posisi belakang satu langkah. |
| 3 | Setiap enqueue berikutnya masuk di belakang nilai-nilai yang sudah menunggu. |
| 4 | Dequeue membaca nilai di depan, lalu memajukan posisi depan satu langkah. |
| 5 | Nilai yang dikembalikan selalu nilai yang sudah menunggu paling lama. |
| 6 | Saat depan bertemu belakang, queue kosong lagi, dan dequeue lebih lanjut adalah error. |
Contoh penerapan
Melakukan enqueue 3, 7, 5, lalu mengosongkan queue:
| Operasi | Queue (depan ke belakang) | Mengembalikan |
|---|---|---|
enqueue(3) | [3] | tidak ada |
enqueue(7) | [3, 7] | tidak ada |
enqueue(5) | [3, 7, 5] | tidak ada |
dequeue() | [7, 5] | 3, nilai paling lama |
dequeue() | [5] | 7 |
dequeue() | [] | 5, nilai paling baru, terakhir |
Kapan memakai queue
| Pakai saat | Hindari saat |
|---|---|
| Pekerjaan harus ditangani sesuai urutan kedatangan: antrean job, buffer request, print spooler | Kamu butuh item terbaru lebih dulu, dan itu adalah stack |
| Kamu menjelajah level demi level, seperti yang dilakukan breadth-first search | Item harus dilayani berdasarkan prioritas, bukan kedatangan, dan untuk itu heap lebih cocok |
| Producer dan consumer berjalan dengan kecepatan berbeda dan butuh buffer di antara keduanya | Kamu perlu mencari atau mengakses lewat indeks ke bagian tengah data |
Kamu ingin penyisipan dan pengambilan O(1) tanpa menggeser elemen | Kamu akan mengimplementasikannya dengan menggeser array di setiap dequeue, yang membuatnya O(n) |
Kode Queue
Implementasi Queue yang rapi dan siap dijalankan dalam Python, JavaScript, Java, C++, C. Pilih bahasa, salin kodenya, atau buka langsung di Coddy Playground.
Kode Queue dalam Python
1from collections import deque2
3queue = deque()4
5# Enqueue three values at the rear6for value in [3, 7, 5]:7 queue.append(value)8 print(f"enqueue {value} -> {list(queue)}")9
10# Dequeue them from the front: first in, first out11while queue:12 value = queue.popleft()13 print(f"dequeue {value} -> {list(queue)}")14
15print("empty:", len(queue) == 0)Kode Queue dalam JavaScript
1// A plain array makes dequeue O(n): shift() moves every element left.2// Track a head index instead, the fix the queue article describes.3const queue = { items: [], head: 0 };4
5function enqueue(value) {6 queue.items.push(value);7}8
9function dequeue() {10 const value = queue.items[queue.head];11 queue.items[queue.head] = undefined; // free the slot12 queue.head += 1;13 // Reclaim space once the consumed prefix dominates.14 if (queue.head * 2 >= queue.items.length) {15 queue.items = queue.items.slice(queue.head);16 queue.head = 0;17 }18 return value;19}20
21const size = () => queue.items.length - queue.head;22
23for (const value of [3, 7, 5]) {24 enqueue(value);25 console.log(`enqueue ${value} -> size ${size()}`);26}27
28// Dequeue from the front: first in, first out, amortized O(1)29while (size() > 0) {30 console.log(`dequeue ${dequeue()} -> size ${size()}`);31}32
33console.log('empty:', size() === 0);Kode Queue dalam Java
1import java.util.ArrayDeque;2import java.util.Queue;3
4public class Main {5 public static void main(String[] args) {6 Queue<Integer> queue = new ArrayDeque<>();7
8 // Enqueue three values at the rear9 for (int value : new int[] {3, 7, 5}) {10 queue.add(value);11 System.out.println("enqueue " + value + " -> " + queue);12 }13
14 // Dequeue them from the front: first in, first out15 while (!queue.isEmpty()) {16 int value = queue.remove();17 System.out.println("dequeue " + value + " -> " + queue);18 }19
20 System.out.println("empty: " + queue.isEmpty());21 }22}Kode Queue dalam C++
1#include <iostream>2#include <queue>3
4int main() {5 std::queue<int> queue;6
7 // Enqueue three values at the rear8 for (int value : {3, 7, 5}) {9 queue.push(value);10 std::cout << "enqueue " << value << " -> size " << queue.size() << "\n";11 }12
13 // Dequeue them from the front: first in, first out14 while (!queue.empty()) {15 int value = queue.front();16 queue.pop();17 std::cout << "dequeue " << value << " -> size " << queue.size() << "\n";18 }19
20 std::cout << "empty: " << std::boolalpha << queue.empty() << "\n";21 return 0;22}Kode Queue dalam C
1#include <stdio.h>2
3#define CAP 164
5int queue[CAP];6int front = 0;7int rear = 0; /* index of the next free slot */8
9int main(void) {10 int values[3] = {3, 7, 5};11
12 /* Enqueue three values at the rear */13 for (int i = 0; i < 3; i++) {14 queue[rear++] = values[i];15 printf("enqueue %d -> size %d\n", values[i], rear - front);16 }17
18 /* Dequeue them from the front: first in, first out */19 while (front < rear) {20 int value = queue[front++];21 printf("dequeue %d -> size %d\n", value, rear - front);22 }23
24 printf("empty: %d\n", front == rear);25 return 0;26}FAQ Queue
Apa arti FIFO?
Apa perbedaan queue dan stack?
O(1); queue mengambil dari depan (FIFO), sedangkan stack mengambil dari ujung yang sama tempat nilai ditambahkan (LIFO). Selain itu, tabel kompleksitas keduanya sama persis.Apa saja operasi utama queue?
enqueue menambahkan nilai di belakang, dequeue mengeluarkan dan mengembalikan nilai terdepan, peek (atau front) membaca nilai terdepan tanpa mengeluarkannya, dan is_empty memberi tahu apakah masih ada yang menunggu. Keempatnya bernilai O(1).Mengapa dequeue lambat jika memakai array biasa?
O(n). Implementasi sebenarnya menghindari hal ini dengan ring buffer yang memajukan indeks depan, atau linked list dengan pointer head. collections.deque di Python dan ArrayDeque di Java sudah melakukannya untukmu, sedangkan list.pop(0) tidak.Apa itu circular queue?
n bisa terus bekerja tanpa batas alih-alih melewati ujung array.