Langsung ke konten
KamusNgoding
Pemula Data-structures 4 menit baca

Memahami Stack (LIFO) dan Queue (FIFO) dalam Struktur Data

#data-structures #beginner #stack #queue

Pendahuluan

Halo, teman-teman developer! Senang sekali bisa kembali lagi di seri struktur data ini. Pada artikel sebelumnya, kita sudah membedah secara mendalam tentang Linked List, baik itu Singly maupun Doubly Linked List. Kita sudah belajar bagaimana sebuah data bisa saling terhubung satu sama lain melalui referensi atau pointer.

Namun, sebuah pointer hanyalah sebuah alat. Pertanyaan besarnya adalah: bagaimana kita menggunakan pointer tersebut untuk mengatur alur data secara logis? Di sinilah kita akan mempelajari dua konsep fundamental yang akan menjadi fondasi utama dalam pembuatan sistem manajemen data: Stack dan Queue.

Dalam artikel kali ini, kita akan mempelajari konsep Stack dengan prinsip LIFO (Last-In, First-Out) dan Queue dengan prinsip FIFO (First-In, First-Out). Kita juga akan menyatukan semua ilmu yang telah kita pelajari dari artikel 1 sampai 3 untuk menyelesaikan proyek akhir kita, yaitu Sistem Antrian Digital. Dengan memahami kedua konsep ini, kamu akan lebih mudah dalam merancang logika aplikasi, mulai dari fitur undo/redo pada text editor hingga sistem antrian pelanggan di Bank BCA atau layanan Gojek.

Konsep Utama 1: Stack (LIFO - Last-In, First-Out)

Stack atau dalam Bahasa Indonesia disebut sebagai “Tumpukan” adalah struktur data linear yang mengikuti prinsip LIFO. Sesuai namanya, elemen yang terakhir kali dimasukkan ke dalam tumpukan akan menjadi elemen yang pertama kali dikeluarkan.

Bayangkan kamu sedang mencuci piring di rumah. Piring yang kamu cuci terakhir akan diletakkan di posisi paling atas. Ketika kamu ingin mengambil piring untuk makan, piring yang paling atas (yang terakhir diletakkan) adalah yang pertama kamu ambil. Itulah esensi dari LIFO.

Operasi Dasar pada Stack

Ada beberapa operasi utama yang wajib kamu kuasai dalam Stack:

  1. Push: Menambahkan elemen baru ke bagian paling atas tumpukan.
  2. Pop: Menghapus dan mengambil elemen dari bagian paling atas tumpukan.
  3. Peek/Top: Melihat elemen yang berada di posisi paling atas tanpa menghapusnya.
  4. isEmpty: Mengecek apakah tumpukan dalam keadaan kosong.

Contoh Implementasi Stack di Python

Mari kita lihat bagaimana implementasi Stack sederhana menggunakan Python.

class Stack:
    def __init__(self):
        # Kita menggunakan list sebagai wadah penyimpanan elemen
        self.items = []

    def is_empty(self):
        return len(self.items) == 0

    def push(self, item):
        # Menambahkan item ke bagian paling atas
        self.items.append(item)
        print(f"Push: {item} berhasil ditambahkan.")

    def pop(self):
        if self.is_empty():
            return "Stack Kosong! Tidak ada yang bisa diambil."
        # Mengambil item terakhir (LIFO)
        removed_item = self.items.pop()
        return removed_item

    def peek(self):
        if self.is_empty():
            return "Stack Kosong!"
        return self.items[-1]

    def size(self):
        return len(self.items)

# --- Uji Coba Stack ---
tumpukan_piring = Stack()

# Menambahkan piring ke tumpukan
tumpukan_piring.push("Piring Keramik Rp 50.000")
tumpukan_piring.push("Piring Melamin Rp 15.000")
tumpukan_piring.push("Piring Plastik Rp 5.000")

print(f"Piring paling atas saat ini: {tumpukan_piring.peek()}")

# Mengambil piring (Pop)
print(f"Mengambil piring: {tumpukan * 1}") # Ini akan mengambil piring plastik
print(f"Mengambil piring: {tumpukan_piring.pop()}")

print(f"Isi tumpukan sekarang: {tumpukan_piring.items}")

Dalam dunia nyata, fitur Undo pada Microsoft Word atau VS Code menggunakan prinsip Stack. Setiap perubahan yang kamu lakukan disimpan dalam tumpukan. Saat kamu menekan Ctrl + Z, program akan melakukan pop pada aksi terakhir yang kamu lakukan.

Konsep Utama 2: Queue (FIFO - First-In, First-Out)

Berbeda dengan Stack, Queue atau “Antrian” menggunakan prinsip FIFO. Artinya, elemen yang pertama kali masuk ke dalam antrian akan menjadi elemen yang pertama kali diproses atau dikeluarkan.

Contoh yang paling mudah ditemukan di Indonesia adalah antrian di kasir Indomaret atau antrian pelanggan di Bank Mandiri. Orang yang datang pertama kali akan dilayani terlebih dahulu. Tidak adil rasanya jika orang yang baru datang langsung dilayani sebelum orang yang sudah menunggu lama, bukan?

Operasi Dasar pada Queue

  1. Enqueue: Menambahkan elemen baru ke bagian belakang (rear/tail) antrian.
  2. Dequeue: Menghapus dan mengambil elemen dari bagian depan (front/head) antrian.
  3. Front: Melihat elemen yang berada di urutan paling depan.
  4. isEmpty: Mengecek apakah antrian kosong.

Contoh Implementasi Queue di Python

from collections import deque

class Queue:
    def __init__(self):
        # Menggunakan deque (double-ended queue) dari library collections
        # karena lebih efisien untuk operasi pop dari depan (O(1))
        self.items = deque()

    def is_empty(self):
        return len(self.items) == 0

    def enqueue(self, item):
        # Menambahkan ke belakang antrian
        self.items.append(item)
        print(f"Enqueue: {item} masuk ke antrian.")

    def dequeue(self):
        if self.is_empty():
            return "Antrian Kosong!"
        # Menghapus dari depan antrian (FIFO)
        return self.items.popleft()

    def front(self):
        if self.is_empty():
            return "Antrian Kosong!"
        return self.items[0]

    def size(self):
        return len(self.items)

# --- Uji Ciber Queue ---
antrian_bank = Queue()

# Pelanggan datang
antrian_bank.enqueue("Budi (Nasabah Tabungan)")
antrian_bank.enqueue("Siti (Nasabah Deposito)")
antrian_bank.enqueue("Andi (Nasabah Kredit)")

print(f"Pelanggan yang sedang dilayani: {antrian_bank.front()}")

# Proses pelayanan
print(f"Melayani: {antrian_bank.dequeue()}")
print(f"Melayani: {antrian_bank.dequeue()}")

print(f"Sisa antrian: {antrian_bank.size()} orang.")

Perbedaan Utama: Stack vs Queue

Agar kamu tidak tertukar, mari kita buat perbandingan sederhana:

FiturStackQueue
Prinsip UtamaLIFO (Last-In, First-Out)FIFO (First-In, First-Out)
AnalogiTumpukan piring/bukuAntrian loket pembayaran
Titik AksesHanya satu ujung (Top)Dua ujung (Front & Rear)
icalPenambahan di satu ujung, penghapusan di ujung yang samaPenambahan di belakang, penghapusan di depan
KegunaanUndo/Redo, Backtracking algoritmaPrinter Spooling, Task Scheduling

Implementasi dalam Proyek: Sistem Antrian Digital

Sekarang, saatnya kita menerapkan semua ilmu yang telah kita pelajari. Kita akan membuat sebuah sistem manajemen antrian sederhana untuk sebuah bank. Kita tidak akan menggunakan list biasa, melainkan menggunakan konsep Linked List yang sudah kita pelajari di artikel sebelumnya agar lebih efisien dalam penggunaan memori saat data bertambah secara dinamis.

Berikut adalah implementasi lengkapnya:

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class AntrianNasabah:
    def __init__(self):
        self.head = None  # Menunjuk ke nasabah pertama (depan)
        self.tail = None  # Menunjuk ke nasabah terakhir (belakang)
        self.count = 0

    def tambah_nasabah(self, nama):
        baru = Node(nama)
        if self.head is None:
            self.head = baru
            self.tail = baru
        else:
            self_tail = self.tail
            self_tail.next = baru
            self.tail = baru
        self.count += 1
        print(f"Nasabah '{nama}' berhasil masuk antrian.")

    def panggil_nasabah(self):
        if self.head is None:
            print("Antrian kosong! Tidak ada nasabah untuk dipanggil.")
            return None
        
        nasabah_dipanggil = self.head.data
        print(f"Memanggil nasabah: {nasabah_dipanggil}")
        
        self.head = self.head.next
        self.count -= 1
        
        if self.head is None:
            self.tail = None
            
        return nasabah_dipanggil

    def tampilkan_antrian(self):
        if self.head is None:
            print("Antrian saat ini kosong.")
            return
        
        print("\n--- Daftar Antrian Saat Ini ---")
        temp = self.head
        index = 1
        while temp:
            print(f"{index}. {temp.data}")
            temp = temp.next
            index += 1
        print("-------------------------------\n")

# --- Eksekusi Program ---
bank_mandiri_simulasi = AntrianNasabah()

# 1. Menambahkan nasabah
bank_mandiri_simulasi.tambah_nasabah("Budi")
bank_mandiri_simulasi.tambah_nasabah("Siti")
bank_mandiri_simulasi.tambah_nasabah("Andi")

# 2. Melihat antrian
bank_mandiri_simulasi.tampilkan_antrian()

# 3. Memanggil nasabah (Proses transaksi)
bank_mandiri_simulasi.panggil_nasabah()
bank_mandiri_simulasi.panggil_nasabah()

# 4. Melihat antrian setelah pemanggilan
bank_mandiri_simulasi.tampilkan_antrian()

Dalam kode di atas, kita menggunakan struktur data Queue yang dibangun di atas Linked List. Ini adalah cara yang paling efisien karena kita tidak perlu menggeser seluruh elemen dalam array saat elemen pertama dihapus (seperti yang terjadi pada list.pop(0) di Python).

Kesimpulan

Kita telah belajar perbedaan mendasar antara Stack (LIFO) dan Queue (FIFO). Kita juga telah melihat bagaimana struktur data dasar seperti Linked List dapat digunakan untuk membangun struktur data yang lebih kompleks seperti Queue untuk menyelesaikan masalah nyata seperti manajemen antrian nasabah.

Memahami struktur data ini adalah kunci utama untuk menulis kode yang efisien dan mampu menangani data dalam skala besar. Sampai jumpa di materi berikutnya!

Artikel Terkait