| 자료구조 | 데이터 추출 방식 | 예시 |
|---|---|---|
| 스택(Stack) | 후입선출: 최근에 삽입된 데이터부터 추출 | 박스 쌓기 |
| 큐(Queue) | 선입선출: 가장 먼저 삽입된 데이터부터 추출 | 줄 서기 |
| 우선순위 큐(Priority Queue) | 우선순위가 가장 높은 데이터부터 추출 | 저렴한/비싼 가격 순으로 데이터 추출 |
-> 즉, 큐는 순서 기반, 우선순위 큐는 값 기반
파이썬에서는 우선순위 큐 기능을 지원하는 라이브러리인 Priority Queue, heapq가 존재
heapq 모듈을 사용해 최소 힙(min-heap) 구현import heapq
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 2)
heapq.heappush(heap, 8)
print(heapq.heappop(heap)) # 2 (가장 작은 값부터 꺼냄)
print(heapq.heappop(heap)) # 5
-값을 넣어 최대 힙처럼 동작시킴heapq.heappush(heap, -5) # push
max_val = -heapq.heappop(heap) # pop and reverse sign
heapq.heappush(heap, (1, "data1")) # 우선순위 1
heapq.heappush(heap, (3, "data2")) # 우선순위 3
import heapq
N = int(input()) # 카드 묶음 수
heap_card = []
# 카드 묶음을 min-heap에 삽입
for _ in range(N):
heapq.heappush(heap_card, int(input()))
# 합친 비용을 누적하지 않은 버전 (오답)
while len(heap_card) > 1:
sum = heapq.heappop(heap_card)
sum = sum + heapq.heappop(heap_card)
heapq.heappush(heap_card, sum)
print(heap_card[0]) # ❌ 총합 아님
sum = pop1 + pop2 구하고, 이걸 다시 heap에 넣는 건 괜찮음heap_card[0]은 마지막으로 합쳐진 묶음의 크기이지, 이게 누적합은 아님total = 0으로 따로 누적 합 저장first + second를 total +=import heapq
N = int(input()) #N개의 숫자 카드 묶음
heap_card = [] #카드 묶음 담을 min heap
total = 0 #누적 합
for i in range(N):
heapq.heappush(heap_card, int(input()))
#이러면 n개의 묶음이 min-heap으로 정리될 것
while len(heap_card) > 1:
#작은 값 두 개 꺼내고 삭제 및 더한 값 다시 넣기
sum = heapq.heappop(heap_card)
sum = sum + heapq.heappop(heap_card)
total = total + sum
heapq.heappush(heap_card, sum)
print(total)
핵심 연산
| 연산 이름 | 설명 |
|---|---|
find(x) | 원소 x가 속한 집합의 대표(root)를 찾음 |
union(x, y) | x와 y가 속한 두 집합을 합침 |
same(x, y) | x와 y가 같은 집합에 속해 있는지 확인 |
유니온 파인드 사용을 위해서는
parent배열 +find/union함수 조합으로 직접 구현해야 함
parent[i] = i로 초기화x가 속합 집합의 대표(루트)를 재귀적으로 찾음def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # 경로 압축 (Path Compression)
return parent[x]
x, y의 루트를 찾아서 한쪽 루트를 다른 쪽으로 연결def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x != root_y:
parent[root_y] = root_x
# 초기화
parent = [i for i in range(n + 1)] # 노드 번호가 1부터 n까지일 경우
# find 함수 (경로 압축 포함)
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # 경로 압축
return parent[x]
# union 함수
def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x != root_y:
parent[root_y] = root_x # 또는 parent[root_x] = root_y
n, m = map(int, input().split())
lst = [] # 연산 리스트
parent = [i for i in range(n+1)] # 초기화
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x != root_y:
parent[root_y] = root_x
for i in range(m):
lst[i] = map(int, input().split()) # ❌ 런타임 에러 발생
if lst[0] == 0:
union(lst[1], lst[2])
else:
if find(lst[1]) == find(lst[2]):
print("YES")
else:
print("NO")
| 문제 | 설명 |
|---|---|
lst[i] = ... | 인덱스를 할당하려 했지만 lst는 빈 리스트라 인덱스 없음 → 런타임 에러 |
lst[0], lst[1] | 리스트에 값을 넣지 못했기 때문에 접근 불가 |
| find는 잘 작성됐지만 | 입력 처리 로직 때문에 전체 코드가 망가짐 |
op, a, b 변수로 직접 받기sys.setrecursionlimit()으로 재귀 깊이 제한 해제import sys
sys.setrecursionlimit(100000)
n, m = map(int, input().split())
parent = [i for i in range(n + 1)]
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # 경로 압축
return parent[x]
def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x != root_y:
parent[root_y] = root_x
for _ in range(m):
op, a, b = map(int, input().split())
if op == 0:
union(a, b)
else:
if find(a) == find(b):
print("YES")
else:
print("NO")