Thuật toán & Cấu trúc dữ liệu/CTDL & Tìm kiếm/Stack & Queue — Cấu trúc dữ liệu cơ bản
3/3
~14 phútCTDL & Tìm kiếm

Stack & Queue — Cấu trúc dữ liệu cơ bản

Hiểu Stack (LIFO) và Queue (FIFO), cách implement, ứng dụng thực tế và bài tập kinh điển.

Stack — Last In, First Out (LIFO)

Hình dung Stack như chồng đĩa: đĩa đặt lên cuối cùng sẽ được lấy ra đầu tiên.

push(1)  push(2)  push(3)  pop()
                   
  ┌─┐     ┌─┐     ┌─┐     ┌─┐
  │1│     │2│     │3│     │2│    → trả về 3
  └─┘     │1│     │2│     │1│
          └─┘     │1│     └─┘
                  └─┘

Operations

OperationMô tảTime
push(x)Thêm phần tử lên đỉnhO(1)
pop()Lấy phần tử ở đỉnh raO(1)
peek()Xem phần tử ở đỉnh (không lấy ra)O(1)
isEmpty()Stack có rỗng khôngO(1)

Implement bằng Array

public class Stack<T> {
    private Object[] data;
    private int top = -1;

    public Stack(int capacity) {
        data = new Object[capacity];
    }

    public void push(T item) {
        data[++top] = item;
    }

    @SuppressWarnings("unchecked")
    public T pop() {
        T item = (T) data[top];
        data[top--] = null;
        return item;
    }

    @SuppressWarnings("unchecked")
    public T peek() {
        return (T) data[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }
}

Ứng dụng: Kiểm tra ngoặc hợp lệ

Bài kinh điển trong coding interview:

public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();

    for (char c : s.toCharArray()) {
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
        } else {
            if (stack.isEmpty()) return false;
            char open = stack.pop();
            if (c == ')' && open != '(') return false;
            if (c == ']' && open != '[') return false;
            if (c == '}' && open != '{') return false;
        }
    }

    return stack.isEmpty();
}

isValid("({[]})");  // true
isValid("([)]");    // false

💡 Stack trong thực tế

  • Undo/Redo trong text editor
  • Call Stack khi gọi hàm đệ quy
  • Browser history (Back button)
  • Expression evaluation (2 + 3 * 4)

Queue — First In, First Out (FIFO)

Hình dung Queue như hàng đợi mua vé: ai đến trước được phục vụ trước.

enqueue(1)  enqueue(2)  enqueue(3)  dequeue()

Front→ ┌─┐     ┌─┬─┐     ┌─┬─┬─┐     ┌─┬─┐ ←Back
       │1│     │1│2│     │1│2│3│     │2│3│    → trả về 1
       └─┘     └─┴─┘     └─┴─┴─┘     └─┴─┘

Operations

OperationMô tảTime
enqueue(x)Thêm vào cuối hàngO(1)
dequeue()Lấy phần tử đầu hàng raO(1)
peek()Xem phần tử đầu hàngO(1)
isEmpty()Queue có rỗng khôngO(1)

Implement bằng LinkedList

public class Queue<T> {
    private static class Node<T> {
        T data;
        Node<T> next;
        Node(T data) { this.data = data; }
    }

    private Node<T> front, back;

    public void enqueue(T item) {
        Node<T> node = new Node<>(item);
        if (back != null) back.next = node;
        back = node;
        if (front == null) front = back;
    }

    public T dequeue() {
        T data = front.data;
        front = front.next;
        if (front == null) back = null;
        return data;
    }

    public boolean isEmpty() {
        return front == null;
    }
}
public void bfs(Node root) {
    Queue<Node> queue = new LinkedList<>();
    queue.add(root);

    while (!queue.isEmpty()) {
        Node current = queue.poll();
        System.out.println(current.value);

        for (Node child : current.children) {
            queue.add(child);
        }
    }
}

ℹ️ Queue trong thực tế

  • Message Queue (RabbitMQ, Kafka)
  • Task scheduling (thread pool)
  • BFS trong graph/tree
  • Print queue (máy in xử lý theo thứ tự)

So sánh Stack vs Queue

StackQueue
Nguyên tắcLIFOFIFO
Thêmpush (đỉnh)enqueue (cuối)
Lấypop (đỉnh)dequeue (đầu)
Ứng dụngUndo, DFS, recursionBFS, scheduling, buffer