Menu
Coddy logo textTech

마지막 업데이트

큐에는 살아 있는 끝이 두 개 있습니다. 새 값은 뒤에서 들어오고 값은 앞에서 빠져나가므로, 가장 오래 기다린 것이 가장 먼저 처리됩니다. 이것이 선입선출(FIFO)이며, 창구 앞에 늘어선 줄이 움직이는 방식과 정확히 같습니다. 뒤에 서고 앞에서부터 처리되기 때문에 기다림이 공정해집니다. 위의 재생을 누르면 값이 한쪽으로 들어와 반대쪽으로 나가는 모습을 볼 수 있습니다.

각 끝을 저마다의 인덱스나 포인터로 추적하기 때문에 두 연산 모두 O(1)이고, 어느 쪽도 나머지 데이터를 옮기지 않습니다. 그래서 큐는 도착 순서대로 일을 처리하는 모든 것을 떠받칩니다. 인쇄 작업, 작업 큐와 메시지 큐, 요청 버퍼, 그리고 너비 우선 탐색이 그렇습니다. 너비 우선 탐색이 그래프를 레벨 단위로 방문하는 이유는 바로 프런티어를 큐에 담아 두기 때문입니다. 제거하는 끝을 뒤로 옮기면 대신 스택이 됩니다.

시간 및 공간 복잡도

링 버퍼나 연결 리스트로 구현한 큐, 즉 두 가지 표준 구현 기준:

연산복잡도비고
인큐(enqueue)O(1)뒤에 쓰고 뒤 인덱스를 한 칸 전진시킨다.
디큐(dequeue)O(1)앞에서 읽고 앞 인덱스를 한 칸 전진시키며, 이동은 없다.
피크(맨 앞 조회)O(1)제거하지 않고 맨 앞 값을 읽는다.
탐색O(n)큐의 용도가 아니다. 안을 보려면 모두 꺼내야 한다.
공간O(n)기다리는 값 하나당 슬롯 하나.

단계별 진행

단계무슨 일이 일어나는가
1큐는 비어 있는 상태로 시작하고, 앞과 뒤가 같은 슬롯을 가리킨다.
2인큐는 뒤에 값을 쓴 다음 뒤를 한 칸 전진시킨다.
3이후의 인큐는 이미 기다리는 값들 뒤에 놓인다.
4디큐는 맨 앞의 값을 읽은 다음 앞을 한 칸 전진시킨다.
5돌아오는 값은 항상 가장 오래 기다린 값이다.
6앞이 뒤와 만나면 큐는 다시 비고, 거기서 더 디큐하면 오류가 된다.

풀이 예제

3, 7, 5를 인큐한 뒤 큐를 모두 비우는 과정:

연산큐 (앞에서 뒤로)반환값
enqueue(3)[3]없음
enqueue(7)[3, 7]없음
enqueue(5)[3, 7, 5]없음
dequeue()[7, 5]3, 가장 오래된 값
dequeue()[5]7
dequeue()[]5, 가장 새로운 값이 마지막

큐를 사용해야 할 때

사용할 때피해야 할 때
도착 순서대로 처리해야 할 때: 작업 큐, 요청 버퍼, 인쇄 스풀러가장 최근 항목이 먼저 필요할 때, 그것은 스택의 일
너비 우선 탐색처럼 레벨 단위로 탐색할 때도착 순서가 아니라 우선순위로 처리해야 할 때, 이 적합
생산자와 소비자의 속도가 달라 사이에 버퍼가 필요할 때데이터 중간을 탐색하거나 색인으로 접근해야 할 때
원소를 옮기지 않고 O(1) 삽입과 제거를 하고 싶을 때디큐할 때마다 배열을 옮기는 방식으로 구현하게 되어 O(n)이 될 때

Queue 코드

Python, JavaScript, Java, C++, C로 작성된 깔끔하고 실행 가능한 Queue 구현입니다. 언어를 선택해 코드를 복사하거나 Coddy 플레이그라운드에서 바로 열어보세요.

Python로 구현한 Queue 코드

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)
이 코드를 Python 플레이그라운드에서 실행하기

큐 자주 묻는 질문

FIFO는 무슨 뜻인가요?
선입선출입니다. 가장 오래 기다린 값이 다음 차례로 처리됩니다. 매표소 앞에 늘어선 줄이 일상적인 비유입니다. 스택은 반대 규율인 LIFO입니다.
큐와 스택의 차이는 무엇인가요?
어느 쪽 끝에서 빼느냐뿐입니다. 둘 다 뒤에 O(1)로 추가합니다. 큐는 앞에서 빼고(FIFO), 스택은 추가한 바로 그 끝에서 뺍니다(LIFO). 그 밖의 복잡도 표는 서로 동일합니다.
큐의 주요 연산은 무엇인가요?
enqueue는 뒤에 값을 추가하고, dequeue는 맨 앞 값을 빼서 반환하며, peek(또는 front)은 제거하지 않고 맨 앞을 읽고, is_empty는 기다리는 것이 있는지 알려줍니다. 네 가지 모두 O(1)입니다.
평범한 배열을 쓰면 왜 디큐가 느린가요?
배열에서 인덱스 0을 제거하면 남은 원소가 모두 왼쪽으로 밀려서 디큐 한 번이 O(n)이 되기 때문입니다. 실제 구현은 앞 인덱스를 전진시키는 링 버퍼나 머리 포인터를 가진 연결 리스트로 이를 피합니다. 파이썬의 collections.deque와 자바의 ArrayDeque는 이를 대신 해 주지만 list.pop(0)은 그렇지 않습니다.
원형 큐란 무엇인가요?
고정 크기 배열로 만든 큐로, 앞과 뒤 인덱스가 끝을 넘어가면 다시 0으로 돌아옵니다. 디큐로 비워진 슬롯을 재사용하므로, 용량이 n인 큐는 배열 끝을 벗어나지 않고 무기한 계속 동작합니다.
실제 프로그램에서 큐는 어디에 쓰이나요?
서비스 사이의 작업 큐와 메시지 큐, 인쇄와 작업 스풀러, 웹 서버의 요청 버퍼, 키보드와 이벤트 버퍼, 생산자-소비자 파이프라인, 그리고 너비 우선 탐색입니다. 여기서는 큐가 바로 순회를 레벨 단위로 진행하게 만듭니다.
Coddy programming languages illustration

Coddy로 알고리즘을 마스터하세요

시작하기