Push/Pop 동작 원리와 시간 복잡도O(N log N), 매번 스캔하면 O(N)이 듭니다.Push/Pop을 O(log N), Top을 O(1)로 처리합니다.new, malloc)인덱스 i 기준:
| 관계 | 공식 |
|---|---|
| 왼쪽 자식 | 2*i + 1 |
| 오른쪽 자식 | 2*i + 2 |
부모 (i > 0) | (i - 1) / 2 |
vector<T>가 가장 일반적입니다.log N이므로 위/아래 이동 비용도 O(log N)입니다.배열: [50, 30, 40, 10, 20, 35]
50
/ \
30 40
/ \ /
10 20 35
30, 40) 누가 큰지는 상관없습니다.Sift Up(또는 Heapify Up)이라고 합니다.예시:
초기: [50, 30, 40, 10, 20, 35]
45 삽입: [50, 30, 40, 10, 20, 35, 45]
부모(40)와 스왑: [50, 30, 45, 10, 20, 35, 40]
종료(부모 50 >= 45)
index 0)에 있으므로 먼저 제거합니다.Sift Down(또는 Heapify Down)이라고 합니다.예시:
초기: [50, 30, 45, 10, 20, 35, 40]
50 제거 + 40 이동: [40, 30, 45, 10, 20, 35]
더 큰 자식(45)와 스왑: [45, 30, 40, 10, 20, 35]
종료(40 >= 35)
| 연산 | 복잡도 | 이유 |
|---|---|---|
Push | O(log N) | 트리 높이만큼 위로 이동 |
Pop | O(log N) | 트리 높이만큼 아래로 이동 |
Top | O(1) | 루트(인덱스 0) 접근 |
Build Heap | O(N) | 바닥부터 Heapify할 때 선형 시간 |
면접 포인트:
Push/Pop이 log N인가?” -> 힙 높이가 log N이기 때문Build Heap은 N log N이 아니라 N인가?” -> 아래 레벨 노드는 이동 거리가 짧아 총합이 선형std::priority_queue<int, std::vector<int>, std::greater<int>> minPQ;
priority_queue 기본은 최대 힙입니다.greater<> 또는 커스텀 비교자를 사용하세요.복잡도 관점:
O(N) 탐색이 필요합니다.O(log N)으로 줄어 대규모 맵에서 체감 성능 차이가 크게 납니다.실전 구현 팁(C++):
std::priority_queue는 decrease-key를 직접 지원하지 않습니다.push하고, pop 시 최신 거리와 다르면 버리는 방식(지연 삭제)을 사용합니다.| 실수 | 문제 |
|---|---|
빈 큐에서 top()/pop() 호출 | 런타임 오류 위험 |
최소 힙인데 기본 priority_queue 사용 | 정반대 순서로 동작 |
Sift Down에서 더 작은 자식과 스왑 | 힙 속성 깨짐 |
| “힙 = 완전 정렬”로 오해 | Top 외 순서에 잘못 의존 |
| 음수 트릭 남용 | 오버플로우/가독성 저하 |
Top이 O(1)인데 Push/Pop은 O(log N)일까?