개발이야기/파이썬

[Python - 알고리즘] 큐

Study & Stack 2025. 5. 26. 17:01
728x90

큐(Queue) 완벽 정리 + 응용 문제


1. 큐란?

큐는 한쪽에서는 데이터가 들어오고, 다른 쪽에서는 데이터가 나가는 선형 자료구조로, 먼저 들어온 데이터가 먼저 나가는 구조(FIFO, First In First Out)입니다.


2. 큐의 기본 동작

  • enqueue(item): 큐에 데이터를 넣는다.
  • dequeue(): 큐에서 가장 먼저 들어온 데이터를 꺼낸다.
  • front(): 큐에서 가장 앞에 있는 데이터를 확인한다.
  • is_empty(): 큐가 비었는지 확인한다.

3. 파이썬 기본 큐 구현

class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item):
        self.items.append(item)

    def dequeue(self):
        if not self.is_empty():
            return self.items.pop(0)
        return None

    def front(self):
        if not self.is_empty():
            return self.items[0]
        return None

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

주의! 위 구현은 pop(0)가 O(n)이라 비효율적입니다.


4. 효율적인 큐 - collections.deque 사용

from collections import deque

queue = deque()

queue.append(10)    # enqueue
queue.append(20)

print(queue[0])     # front 출력: 10
print(queue.popleft()) # dequeue: 10
print(queue.popleft()) # dequeue: 20

5. 큐 응용문제 1: BFS (너비 우선 탐색)

문제: 그래프를 큐를 사용해 너비 우선 탐색으로 방문하는 코드를 작성하세요.

from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)

    while queue:
        node = queue.popleft()
        print(node, end=' ')
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)

graph = {
    'A': ['B', 'C'],
    'B': ['D', 'E'],
    'C': ['F'],
    'D': [],
    'E': ['F'],
    'F': []
}

bfs(graph, 'A')  # 출력: A B C D E F

6. 큐 응용문제 2: 프린터 큐 (우선순위 큐 변형)

문제: 여러 문서가 우선순위를 가지고 프린터 큐에 대기 중입니다. 현재 큐의 맨 앞 문서보다 우선순위가 높은 문서가 있으면 현재 문서는 뒤로 이동합니다. 주어진 문서의 출력 순서를 구하세요.

예:

  • 문서 우선순위 = [2, 1, 3, 2]
  • 몇 번째로 인쇄되는지 알고 싶은 문서 위치 = 2 (우선순위 3)
from collections import deque

def printer_queue(priorities, location):
    queue = deque([(i, p) for i, p in enumerate(priorities)])
    print_order = 0

    while queue:
        cur = queue.popleft()
        if any(cur[1] < other[1] for other in queue):
            queue.append(cur)
        else:
            print_order += 1
            if cur[0] == location:
                return print_order

# 테스트
print(printer_queue([2, 1, 3, 2], 2))  # 출력: 1

7. 큐 응용문제 3: 캐시 구현 (LRU 정책)

문제: 큐를 사용해 캐시 크기 제한(LRU 정책) 내에서 가장 오래된 데이터를 제거하며 새 데이터를 넣는 코드를 작성하세요.

from collections import deque

class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache = deque()

    def access(self, item):
        if item in self.cache:
            self.cache.remove(item)
        elif len(self.cache) >= self.capacity:
            self.cache.popleft()
        self.cache.append(item)

    def get_cache(self):
        return list(self.cache)

cache = LRUCache(3)
cache.access('A')
cache.access('B')
cache.access('C')
print(cache.get_cache())  # ['A', 'B', 'C']
cache.access('B')
print(cache.get_cache())  # ['A', 'C', 'B']
cache.access('D')
print(cache.get_cache())  # ['C', 'B', 'D']

8. 큐 정리표

특징 설명
구조 FIFO (First In First Out)
주요 연산 enqueue, dequeue, front, is_empty
시간복잡도 deque 사용 시 모든 연산 O(1)
응용분야 BFS, 프린터 큐, 프로세스 스케줄링, 캐시 관리
728x90