카테고리 없음
11월 자료구조 - 힙(Heap)
Halfand
2024. 12. 4. 12:19
이번에는 힙(Heap) 자료구조를 다뤄보겠습니다. 힙은 주로 우선순위 큐(Priority Queue)를 구현할 때 사용됩니다.
1. 자료구조 주제
힙 (Heap)
2. 고른 자료구조의 정의
힙(Heap)은 완전 이진 트리(Complete Binary Tree)로, 부모 노드가 자식 노드보다 우선순위가 높거나 낮은 특성을 갖는 자료구조입니다. 힙은 크게 두 가지 종류로 나뉩니다:
- 최소 힙(Min Heap): 부모 노드가 자식 노드보다 작거나 같은 값을 가집니다. 따라서 루트 노드는 트리에서 가장 작은 값을 가집니다.
- 최대 힙(Max Heap): 부모 노드가 자식 노드보다 크거나 같은 값을 가집니다. 루트 노드는 트리에서 가장 큰 값을 가집니다.
힙은 주로 우선순위 큐에서 사용되며, 힙을 이용하면 데이터의 삽입과 삭제를 O(log n) 시간 복잡도로 처리할 수 있습니다. 힙을 이용한 알고리즘으로는 다익스트라 알고리즘, 힙 정렬(Heap Sort) 등이 있습니다.
3. 고른 자료구조를 구현한 파이썬 코드 전문
파이썬에서는 heapq 모듈을 사용하면 최소 힙을 쉽게 구현할 수 있습니다. 아래는 직접 최소 힙을 구현한 예시입니다.
class MinHeap:
def __init__(self):
self.heap = []
def parent(self, i):
return (i - 1) // 2
def left_child(self, i):
return 2 * i + 1
def right_child(self, i):
return 2 * i + 2
def insert(self, key):
# 힙에 값을 삽입
self.heap.append(key)
self._heapify_up(len(self.heap) - 1)
def _heapify_up(self, i):
# 삽입 후 힙 속성 유지 (상향식)
while i > 0 and self.heap[self.parent(i)] > self.heap[i]:
self.heap[self.parent(i)], self.heap[i] = self.heap[i], self.heap[self.parent(i)]
i = self.parent(i)
def extract_min(self):
if len(self.heap) == 0:
return "Heap is empty"
if len(self.heap) == 1:
return self.heap.pop()
root = self.heap[0]
self.heap[0] = self.heap.pop()
self._heapify_down(0)
return root
def _heapify_down(self, i):
# 삭제 후 힙 속성 유지 (하향식)
smallest = i
left = self.left_child(i)
right = self.right_child(i)
if left < len(self.heap) and self.heap[left] < self.heap[smallest]:
smallest = left
if right < len(self.heap) and self.heap[right] < self.heap[smallest]:
smallest = right
if smallest != i:
self.heap[i], self.heap[smallest] = self.heap[smallest], self.heap[i]
self._heapify_down(smallest)
def peek(self):
# 최소값 반환 (삭제하지 않음)
if len(self.heap) > 0:
return self.heap[0]
return "Heap is empty"
# 예시 사용
min_heap = MinHeap()
min_heap.insert(3)
min_heap.insert(1)
min_heap.insert(6)
min_heap.insert(5)
min_heap.insert(9)
min_heap.insert(8)
print("Min value:", min_heap.peek()) # 최소값 출력
print("Extracted min:", min_heap.extract_min()) # 최소값 추출
print("New min value:", min_heap.peek()) # 새로운 최소값 출력
4. 고른 자료구조의 원리를 어떻게 파이썬으로 구현했는지
위 코드는 최소 힙(Min Heap)을 파이썬으로 구현한 예시입니다. 코드 해설을 해보겠습니다.
- MinHeap 클래스: MinHeap 클래스는 힙을 나타내며, 힙에서 자주 사용되는 연산들을 메서드로 구현합니다. self.heap 리스트는 힙을 저장하는 자료구조입니다.
- parent, left_child, right_child 메서드: 힙에서 부모와 자식 노드를 찾는 메서드입니다. 각각의 인덱스를 기준으로 부모, 왼쪽 자식, 오른쪽 자식의 인덱스를 계산합니다. 부모 인덱스는 (i - 1) // 2, 왼쪽 자식은 2 * i + 1, 오른쪽 자식은 2 * i + 2입니다.
- insert 메서드: 이 메서드는 새로운 값을 힙에 삽입합니다. self.heap.append(key)를 사용하여 값을 힙의 마지막에 추가한 후, _heapify_up 메서드를 호출하여 힙 속성을 상향식으로 복구합니다.
- _heapify_up 메서드: 삽입된 값을 올바른 위치로 올려주는 메서드입니다. 자식 노드가 부모 노드보다 작으면 두 값을 교환하며, 부모 노드가 더 이상 자식 노드보다 크지 않으면 반복을 종료합니다.
- extract_min 메서드: 이 메서드는 힙의 루트 노드(최소값)를 삭제하고 반환합니다. 루트 노드를 마지막 노드와 교환한 후, _heapify_down 메서드를 호출하여 힙 속성을 하향식으로 복구합니다.
- _heapify_down 메서드: 루트 노드의 자식들 중 가장 작은 값을 부모 노드와 교환하며, 힙 속성을 유지합니다. 자식 노드가 부모 노드보다 작으면 계속해서 교환을 반복합니다.
- peek 메서드: 힙에서 가장 작은 값을 반환합니다. 루트 노드는 항상 최소값을 가지므로 이를 반환합니다.
5. 느낀점
힙은 우선순위 큐를 구현하는 데 매우 유용한 자료구조입니다. 특히 삽입과 삭제 연산을 O(log n) 시간 복잡도로 처리할 수 있기 때문에 효율적인 데이터 처리에 적합합니다. 파이썬에서 리스트를 사용하여 힙을 구현하는 과정에서 힙의 상향식과 하향식 속성에 대해 잘 이해할 수 있었습니다. 힙은 다익스트라 알고리즘과 같은 많은 알고리즘에서 중요한 역할을 하므로, 이를 잘 이해하고 활용하는 것이 매우 중요합니다. 직접 구현해보면서 힙의 원리와 효율성에 대해 실감할 수 있었고, 이 자료구조가 실제 문제 해결에 어떻게 쓰일 수 있는지에 대해 더 깊은 이해를 얻을 수 있었습니다.