728x90
반응형
Python의 내장 모듈인 heapq는 힙(Heap) 자료 구조를 제공하며, 기본적으로 최소힙(Min-Heap)으로 동작합니다. 최소힙은 가장 작은 요소를 항상 루트 노드로 유지하는 완전 이진 트리입니다.
하지만 최대힙(Max-Heap)은 지원하지 않으므로, 특정 트릭을 사용하여 최대힙을 구현해야 합니다.
1. 최소힙(Min-Heap) 구현
기본 동작
- heapq는 리스트를 힙처럼 다룰 수 있도록 제공합니다.
- heapq.heappush(heap, item): 힙에 새로운 요소를 추가합니다.
- heapq.heappop(heap): 힙에서 가장 작은 요소를 제거하고 반환합니다.
예제 코드
import heapq
# 최소힙 생성
min_heap = []
# 요소 추가
heapq.heappush(min_heap, 3)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 4)
heapq.heappush(min_heap, 2)
print("Min-Heap:", min_heap) # [1, 2, 4, 3]
# 가장 작은 요소 제거 및 반환
smallest = heapq.heappop(min_heap)
print("Popped element:", smallest) # 1
print("After pop:", min_heap) # [2, 3, 4]
결과
- 요소를 추가하면 내부적으로 힙의 속성을 유지합니다.
- heappop을 호출하면 가장 작은 값을 제거하고 반환합니다.
2. 최대힙(Max-Heap) 구현
Python의 heapq는 최소힙만 지원하므로, 음수값을 사용하여 최대힙처럼 동작하도록 만들 수 있습니다:
- 삽입 시 값에 -1을 곱해 음수로 저장.
- 제거 시 다시 -1을 곱해 원래 값으로 복구.
예제 코드
import heapq
# 최대힙 생성
max_heap = []
# 요소 추가 (음수로 변환하여 추가)
heapq.heappush(max_heap, -3)
heapq.heappush(max_heap, -1)
heapq.heappush(max_heap, -4)
heapq.heappush(max_heap, -2)
# 힙 내부 상태 확인 (음수로 저장됨)
print("Max-Heap (inverted):", max_heap) # [-4, -2, -3, -1]
# 가장 큰 요소 제거 및 반환 (다시 양수로 변환)
largest = -heapq.heappop(max_heap)
print("Popped element:", largest) # 4
print("After pop:", [-x for x in max_heap]) # [3, 1, 2]
결과
- 힙에 삽입할 때 음수로 변환하여 최대값을 루트로 유지합니다.
- 제거 시 음수를 다시 양수로 변환해 원래 값을 반환합니다.
3. 최소힙과 최대힙을 동시에 사용하는 경우
어떤 문제에서는 최소힙과 최대힙을 함께 사용해야 할 때가 있습니다. 예를 들어, 중간값을 빠르게 구하기 위해 최소힙과 최대힙을 사용하는 경우가 있습니다.
예제: 중간값 유지
import heapq
min_heap = [] # 최소힙 (큰 절반 저장)
max_heap = [] # 최대힙 (작은 절반 저장, 음수로 변환)
def add_number(num):
if not max_heap or num <= -max_heap[0]:
heapq.heappush(max_heap, -num) # 최대힙에 추가
else:
heapq.heappush(min_heap, num) # 최소힙에 추가
# 크기 조정 (최대힙 크기가 최소힙보다 크거나 같게 유지)
if len(max_heap) > len(min_heap) + 1:
heapq.heappush(min_heap, -heapq.heappop(max_heap))
elif len(min_heap) > len(max_heap):
heapq.heappush(max_heap, -heapq.heappop(min_heap))
def find_median():
if len(max_heap) == len(min_heap):
return (-max_heap[0] + min_heap[0]) / 2
return -max_heap[0]
# 예제 사용
add_number(1)
add_number(5)
add_number(2)
add_number(10)
add_number(6)
print("Median:", find_median()) # Median: 5
4. 힙 정렬 구현
힙을 활용하면 정렬도 쉽게 구현할 수 있습니다.
예제 코드
import heapq
def heap_sort(iterable):
heap = []
for value in iterable:
heapq.heappush(heap, value) # 요소를 힙에 추가
sorted_list = [heapq.heappop(heap) for _ in range(len(heap))]
return sorted_list
nums = [5, 1, 8, 3, 7, 2]
print("Heap Sort:", heap_sort(nums)) # [1, 2, 3, 5, 7, 8]
5. 정리
기능 최소힙 최대힙
| 사용 방법 | heappush, heappop | heappush(-value), -heappop() |
| 루트 노드 값 | 가장 작은 값 | 가장 큰 값 |
| 활용 사례 | 우선순위 큐, K번째 작은 값 찾기 | 최대값 추적, K번째 큰 값 찾기 |
| 예제 코드 | 기본 제공 | 음수 변환을 통해 구현 |
'Category > Python' 카테고리의 다른 글
| 딕셔너리 확장 자료구조 Counter 사용하기 (1) | 2024.11.20 |
|---|---|
| Python의 collections 모듈 사용하기 (0) | 2024.11.20 |
| 파이썬 정렬 함수 sort()와 sorted() 차이점 (0) | 2024.11.18 |
| Python의 itertools 모듈에서 제공하는 주요 함수 정리 (0) | 2024.11.18 |
| Python에서 __init__과 self의 역할 (0) | 2024.11.17 |