
루트 노드가 언제나 최댓값 또는 최솟값을 갖는다
완전 이진 트리여야 한다
완전 이진 트리
- 높이 k인 완전 이진 트리
- 레벨 k-2 까지는 모든 노드가 2개의 자식을 가진 포화 이진 트리
- 레벨 k-1에서는 왼쪽부터 노드가 순차적으로 채워져 있는 이진 트리
| 이진 탐색 트리 | 힙 | |
|---|---|---|
| 원소들은 완전히 크기 순으로 정렬되어 있는가? | O | X (느슨한 정렬) |
| 특정 키 값을 갖는 원소를 빠르게 검색할 수 있는가? | O | X |
| 부가의 제약 조건은 어던 것인가? | - | 완전 이진 트리여야 한다 |

| index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| data8 | - | 30 | 24 | 12 | 18 | 21 | 8 | 6 | 4 | 2 | 19 |
class MaxHeap:
def __init__(self):
self.data = [None]
트리의 마지막 자리에 새로운 원소를 임시로 저장
부모 노드와 키 값을 비교하여 위로, 위로 이동 (자리를 바꾸며)
→ 제약 조건을 만족할 때까지 이동

class MaxHeap:
def insert(self, item):
self.data.append(item)
new = len(self.data) - 1
parent = new // 2
while new > 1 and self.data[parent] < self.data[new]:
self.data[parent], self.data[new] = self.data[new], self.data[parent]
new, parent = parent, parent//2
자식 노드들과의 대소 비교 최대 횟수: 2 *
⇒ 최악의 복잡도 O()의 삭제 연산

class MaxHeap:
def remove(self):
if len(self.data) > 1:
self.data[1], self.data[-1] = self.data[-1], self.data[1]
data = self.data.pop(-1)
self.maxHeapify(1)
else:
data = None
return data
## 틀렸다고 나오는데 왜 틀렸는지 모르겠다
def maxHeapify(self, i):
# 왼쪽 자식 (left child) 의 인덱스를 계산합니다.
left = i * 2
# 오른쪽 자식 (right child) 의 인덱스를 계산합니다.
right = i * 2 + 1
smallest = i
# 왼쪽 자식이 존재하는지, 그리고 왼쪽 자식의 (키) 값이 (무엇보다?) 더 큰지를 판단합니다.
if left < len(self.data) and self.data[left] > self.data[smallest]
:
# 조건이 만족하는 경우, smallest 는 왼쪽 자식의 인덱스를 가집니다.
smallest = left
# 오른쪽 자식이 존재하는지, 그리고 오른쪽 자식의 (키) 값이 (무엇보다?) 더 큰지를 판단합니다.
if right < len(self.data) and self.data[right] > self.data[smallest]
:
# 조건이 만족하는 경우, smallest 는 오른쪽 자식의 인덱스를 가집니다.
samllest = right
if smallest != i:
# 현재 노드 (인덱스 i) 와 최댓값 노드 (왼쪽 아니면 오른쪽 자식) 를 교체합니다.
self.data[i], self.data[smallest] = self.data[smallest], self.data[i]
# 재귀적 호출을 이용하여 최대 힙의 성질을 만족할 때까지 트리를 정리합니다.
self.maxHeapify(smallest)
→ 양방향 연결 리스트로 구현했을 때보다 효율적
def heapsort(unsorted):
H = MaxHeap()
for item in unsorted:
H.insert(item)
sorted = []
d = H.remove()
while d:
sorted.append(d)
d = H.remove()
return sorted
import heapq
heapq.heapify(L) # 리스트 L로부터 min heap 구성
m = heapq.heappop(L) # min heap L에서 최솟값 삭제 (반환)
heapq.heappush(L, x) # min heap L에 원소 x 삽입