부모가 항상 자식보다 크거나(최대 힙, Max Heap) 작은(최소 힙, Min Heap) 완전 이진 트리(Complete Binary Tree). 형제끼리의 순서는 정하지 않는다. 가장 크거나 작은 값이 항상 루트에 있어 꺼내기 쉽다.
배열로 표현한다
완전 이진 트리라서(왼쪽부터 빈틈없이 채운다) 포인터 없이 배열 하나로 담을 수 있다. 인덱스 n인 노드의 왼쪽 자식은 2n + 1, 오른쪽은 2n + 2, 부모는 Math.floor((n - 1) / 2)다.
연산
- 삽입: 배열 끝에 넣고, 부모보다 크면(최대 힙) 자리를 바꾸며 올라간다(bubble up)
- 꺼내기: 루트를 빼고, 마지막 원소를 루트로 옮긴 뒤 더 큰 자식과 바꾸며 내려간다(sink down, heapify)
function push(heap: number[], v: number) {
heap.push(v)
let i = heap.length - 1
while (i > 0) {
const p = Math.floor((i - 1) / 2)
if (heap[p] >= heap[i]) break
;[heap[p], heap[i]] = [heap[i], heap[p]]
i = p
}
}복잡도
삽입과 꺼내기는 트리 높이만큼인 O(log n), 최댓값 확인은 O(1)이다. 특정 값 찾기는 O(n)으로, 힙은 탐색용이 아니다(이진 탐색 트리와 다른 점).
우선순위 큐를 구현하는 표준 방법이고, 다익스트라 같은 그래프 알고리즘과 힙 정렬(Heapsort)에 쓰인다. 정렬 알고리즘 비교는 정렬 알고리즘.