힙은 힙의 특성(최소 힙
Min Heap
)에서는 부모가 항상 자식보다 작거나 같다) 을
만족하는 거의 완전한 트리Almost Complete Tree
인 특수한 트리 기반의 자료구조다.
J.W.J 윌리엄스 John William Joseph Williams (1930.9.2 - 2012.9.29) , 영국의 컴퓨터 과학자가 1964년 힙 정렬 알고리즘을 고안하면서 설계
완전 이진 트리의 일종
완전 이진트리 Complete Binary Tree
완전 이진트리(Complete Binary Tree)는 노드를 삽입할 때, 왼쪽부터 차례대로 삽입하는 트리이다.
예를들어서 [그림 1]의 경우는 완전이진트리가 맞지만, [그림 2]와 같은 경우는 완전 이진트리가 아니다.
그림1) 완전 이진 트리 예 / 출처 : https://juhee-maeng.tistory.com/94
그림 2) 불완전 이진 트리 예 / 출처 : https://juhee-maeng.tistory.com/94
우선순위 큐를 사용할때 활용
heapq
모듈로 파이썬내에 구현되어 있음
최소 힙은 부모가 항상 자식 보다 작다 → 루트 값이 가장 작은 값을 갖게 된다
우선순위 큐 ADT(추상 자료형)는 주로 힙으로 구현
힙은 정렬된 구조가 아니다. (반정렬 상태, 느슨한 정렬 상태)
최소 힙의 경우 부모 노드가 항상 작다는 조건만 만족하며 → 요소들은 서로 정렬되어 있지 않다.
힙(heap)의 종류
출처:https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html
이진 힙 Binary Heap
이진힙의 배열 표현
힙의 활용 예시
우선순위 큐
다익스트라 알고리즘 구현
프림 알고리즘 Prim's Algorithm 구현
힙 정렬과 최소 신장 트리 Minimum Spanning Tree 구현
중앙값의 근사값 Approximation 구할 때
class BinaryHeap(object):
def __init__(self):
self.items = [None] #0번 인덱스를 사용하지 않기 위한 초기값
def __len__(self):
return len(self.items) -1 # 메소드 호출시 최대 길이보다 하나 작은 값 리턴
업힙 up-heap
percolate_up()
이라는 함수로 정의insert()
⇒ (기존 heapq
모듈의 heapq.heappush()
와 대응)https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html
# percolate_up 함수 정의
# 1. data는 leaf 노드에 인서트
# 2. binary heap의 조건( heap property ) 을 맞추기 위해 inserted data 는 점차 root 방향으로 올라간다.
# 3. 재귀적으로 반복
def _percolate_up(self): # '_' => PEP 8에 따른 내부함수표기
i = len(self)
parent = i // 2
while parent >= 0:
if self.items[i] < self.items[parent]:
self.items[parent], self.items[i] = self.items[i] , self.items[parent]
i = parent
parent = i // 2
#삽입 하기위한 insert 함수 정의
def insert(self, k)
self.items.append(k)
self._percolate_up()
다운 힙 Down-Heap
https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html
이진 힙에서요소의 추출 및 삭제
다운 힙 Down-Heap
percolate_down()
이라는 함수로 구현extract()
함수 호출로 실행 (기존 heapq
모듈의 heapq.heappop()
와 대응)percolate_down()
이 실행
def _percolate_down(self, idx):
left = idx * 2
right = idx * 2 + 1
smallest = idx
if left <= len(self) and self.items[left] < self.items[smallest]:
smallest = left
if right <= len(self) and self.items[right] < self.items[smallest]:
smallest = right
if smallest != idx:
self.items[idx], self.items[smallest] = self.items[smallest], self.items[idx]
self._percolate_down(smallest)
def extract(self):
extracted = self.items[1]
self.item[1] = self.items[len(self)]
self.item.pop()
self._percolate_down(1)
return extracted
#이진 힙 클래스 구현
class BinaryHeap(object):
def __init__(self):
self.items = [None] #0번 인덱스를 사용하지 않기 위한 초기값
def __len__(self):
return len(self.items) -1 # 메소드 호출시 최대 길이보다 하나 작은 값 리턴
#삽입 시 실행, 반복 구조 구현
def _percolate_up(self): # '_' => PEP 8에 따른 내부함수표기
i = len(self)
parent = i // 2
while parent >= 0:
if self.items[i] < self.items[parent]:
self.items[parent], self.items[i] = self.items[i] , self.items[parent]
i = parent
parent = i // 2
#삽입 하기위한 insert 함수 정의
def insert(self, k)
self.items.append(k)
self._percolate_up()
#추출시 실행, 재귀 구조 구현
def _percolate_down(self, idx):
left = idx * 2
right = idx * 2 + 1
smallest = idx
if left <= len(self) and self.items[left] < self.items[smallest]:
smallest = left
if right <= len(self) and self.items[right] < self.items[smallest]:
smallest = right
if smallest != idx:
self.items[idx], self.items[smallest] = self.items[smallest], self.items[idx]
self._percolate_down(smallest)
def extract(self):
extracted = self.items[1]
self.item[1] = self.items[len(self)]
self.item.pop()
self._percolate_down(1)
return extracted