본문으로 건너뛰기
김신건의 로그

큐 (Queue)

· 수정 · 📖 약 3분 · 1,038자/단어 #algorithm #data-structure #queue
queue, 큐, FIFO, 원형 큐, circular queue

정의

큐 (Queue)FIFO (First In, First Out) 순서로 원소를 관리하는 추상 자료구조입니다. push(x) (또는 enqueue), pop() (또는 dequeue), front() 세 연산만 제공하며, 가장 먼저 삽입된 원소만 접근 가능합니다.

C++ STL std::queue, Python collections.deque, Java LinkedList / ArrayDeque 로 기본 제공됩니다.

문제 상황과 동기

BFS (너비 우선 탐색), 작업 스케줄링, 프린터 큐, 윈도우 처리 등 “먼저 들어온 것을 먼저 처리” 해야 하는 모든 문제에서 큐가 필수입니다.

  • naive: 배열 맨 앞 원소 제거는 O(N) (뒤 원소들을 앞으로 shift).
  • circular queue: 배열 + head/tail 포인터로 push/pop 모두 O(1).
  • deque (양방향 큐): 양 끝에서 모두 push/pop 가능. BFS 변형 (0-1 BFS, deque BFS) 에서 필수.

핵심 통찰: BFS = 레벨 순서 순회 = 큐. DFS 는 스택, BFS 는 큐.

시각화

핵심 아이디어

invariant: front 는 가장 오래된 원소, back 은 가장 최근 원소. 삽입 / 삭제 순서가 순서 그대로.

원형 큐 (Circular Queue)

배열 크기 N 으로 고정, head 와 tail 인덱스를 mod N 으로 순환. 배열 재할당 없이 push/pop O(1).

push(x):
    queue[tail] = x
    tail = (tail + 1) % N

pop():
    result = queue[head]
    head = (head + 1) % N
    return result

full():
    return (tail + 1) % N == head

Deque (양방향 큐)

front / back 양쪽에서 모두 push/pop. 0-1 BFS (가중치 0 / 1 인 간선), 슬라이딩 윈도우 최소 / 최대 같은 문제에서 핵심.

push_front(x), push_back(x)
pop_front(), pop_back()

알고리즘

기본 큐 (원형 배열 구현)

class CircularQueue:
    data = array of size N
    head = 0
    tail = 0

    push(x):
        if full():
            error "queue full"
        data[tail] = x
        tail = (tail + 1) % N

    pop():
        if empty():
            error "queue empty"
        result = data[head]
        head = (head + 1) % N
        return result

    front():
        return data[head]

    empty():
        return head == tail

    full():
        return (tail + 1) % N == head

BFS (너비 우선 탐색)

bfs(start):
    queue = empty
    visited = set()
    queue.push(start)
    visited.add(start)
    while queue not empty:
        u = queue.pop()
        for v in neighbors(u):
            if v not in visited:
                visited.add(v)
                queue.push(v)

구현

// BFS 기본 (인접 리스트 그래프)
#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, m, start; cin >> n >> m >> start;
  vector<vector<int>> adj(n + 1);
  for (int i = 0; i < m; i++) {
      int u, v; cin >> u >> v;
      adj[u].push_back(v);
      adj[v].push_back(u);
  }
  vector<int> dist(n + 1, -1);
  queue<int> q;
  q.push(start);
  dist[start] = 0;
  while (!q.empty()) {
      int u = q.front(); q.pop();
      for (int v : adj[u]) {
          if (dist[v] == -1) {
              dist[v] = dist[u] + 1;
              q.push(v);
          }
      }
  }
  for (int i = 1; i <= n; i++)
      cout << dist[i] << (i == n ? "\n" : " ");
}
stdin
5 5 1
1 2
1 3
2 4
3 4
4 5
결과
0 1 1 2 3

원형 큐 예제 (수동 구현)

// 원형 큐 (배열 + head/tail 포인터)
#include <bits/stdc++.h>
using namespace std;
int main() {
  int q; cin >> q;
  vector<int> data(100005);
  int head = 0, tail = 0;
  while (q--) {
      string cmd; cin >> cmd;
      if (cmd == "push") {
          int x; cin >> x;
          data[tail++] = x;
      } else if (cmd == "pop") {
          if (head == tail) cout << "-1\n";
          else cout << data[head++] << "\n";
      } else if (cmd == "front") {
          if (head == tail) cout << "-1\n";
          else cout << data[head] << "\n";
      } else if (cmd == "size") {
          cout << (tail - head) << "\n";
      } else if (cmd == "empty") {
          cout << (head == tail ? 1 : 0) << "\n";
      }
  }
}
stdin
7
push 1
push 2
front
pop
pop
pop
empty
결과
1
1
2
-1
1

복잡도

항목
pushO(1)
popO(1)
frontO(1)
공간O(N)
BFS 전체O(V + E) - 각 정점 / 간선 1번씩 방문

변형 / 활용

패턴설명예제
BFS (너비 우선 탐색)레벨 순서 순회. 최단 거리 (가중치 1)BOJ 1260, 7576
0-1 BFS가중치 0 / 1. 가중치 0 간선은 push_front, 1 은 push_backBOJ 13549
Deque (양방향 큐)슬라이딩 윈도우 최소 / 최대. 단조 dequeBOJ 11003
우선순위 큐 (힙)가중치 있는 BFS → DijkstraBOJ 1753
원형 큐고정 크기 버퍼. 프린터 큐BOJ 1966
멀티소스 BFS여러 시작점 동시 큐에 넣음토마토, 불

함정

1. pop() 전 empty 체크

큐가 비었는데 pop 하면 런타임 에러.

if (!q.empty()) q.pop();

2. 배열 큐에서 인덱스 범위

원형 큐 구현 시 (tail + 1) % N == head 조건 (full) 과 head == tail (empty) 을 구분해야 합니다. 한 칸을 희생하거나, 별도 size 변수 관리.

3. Python list.pop(0) 은 O(N)

list.pop(0) 은 맨 앞 제거 + 뒤 원소 shift 로 O(N). 반드시 collections.deque 사용.

from collections import deque
q = deque()
q.append(x)    # push
q.popleft()    # pop O(1)

4. Java Queue.remove() vs poll()

remove() 는 빈 큐에 예외, poll() 은 null 반환. 안전하게 poll() 사용.

Integer val = q.poll();   // null if empty
if (val != null) { ... }

5. BFS 에서 방문 체크 시점

큐에 넣을 때 visited 마크해야 중복 방문 방지. pop 할 때 마크하면 같은 정점이 여러 번 큐에 들어갑니다.

if (!visited[v]) {
    visited[v] = true;   // 여기서 마크
    q.push(v);
}

BOJ 연습 문제

번호제목정답률링크
BOJ 10845-kokoa-lab
BOJ 1260DFS와 BFS-kokoa-lab
BOJ 7576토마토-kokoa-lab
BOJ 1966프린터 큐-kokoa-lab
BOJ 13549숨바꼭질 3 (0-1 BFS)-kokoa-lab

참고

이 글의 용어 (3개)
너비 우선 탐색 (BFS)algorithm
정의 너비 우선 탐색 (Breadth-First Search, BFS) 는 그래프 G=(V, E) 에서 시작 정점 s 로부터 가까운 정점부터 순서대로 방문하는 알고리즘. 큐 (F…
덱 (Deque)algorithm
정의 Deque (덱, double-ended queue) 는 양쪽 끝에서 O(1) push/pop 이 가능한 선형 자료구조. 큐 + 스택의 일반화. 내부 구현은 대개 chunk…
스택 (Stack)algorithm
정의 스택 (Stack) 은 LIFO (Last In, First Out) 순서로 원소를 관리하는 추상 자료구조입니다. , , 세 연산만 제공하며, 가장 최근 삽입된 원소만 접근…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기