12강 / 20강
힙과 우선순위 큐 — 가장 급한 것이 맨 위로
줄 선 순서가 아니라 중요도 순서로
응급실에 손가락을 벤 사람이 먼저 왔고, 그다음 심장마비 환자가 왔습니다. 큐(FIFO)대로라면 손가락이 먼저겠죠. 하지만 그러면 안 됩니다.
줄 선 순서가 아니라 급한 순서로 꺼내야 하는 상황이 있습니다. 이런 걸 우선순위 큐(priority queue)라고 하고, 이걸 빠르게 만드는 자료구조가 힙(heap)입니다.
🐢 리스트로 만들면
넣기는 빠르지만 꺼낼 때마다전부 훑어서 최솟값을 찾아야 함
또는 넣을 때마다 정렬 — 역시 느림
⚡ 힙으로 만들면
넣기도 꺼내기도 높이만큼만1000개여도 약 10번
맨 위는 언제나 최솟값
힙의 규칙 — 이진 탐색 트리보다 느슨합니다
최소 힙의 규칙
모든 노드에 대해 — 부모 ≤ 자식. 왼쪽·오른쪽 사이에는 아무 규칙도 없습니다.
11강의 이진 탐색 트리는 완전한 정렬을 유지했지만, 힙은 "맨 위가 최솟값"만 지킵니다. 규칙이 느슨한 대신 유지 비용이 싸요. 우리가 필요한 건 "가장 급한 것 하나"뿐이니까요.
그리고 힙은 빈틈없이 위에서부터 왼쪽부터 채워진 트리라서, 놀랍게도 리스트 하나로 표현할 수 있습니다.
ㅇ번 노드의 부모 →(ㅇ-1) // 2ㅇ번 노드의 왼쪽 자식 →2*ㅇ + 1, 오른쪽 자식 →2*ㅇ + 2
파이썬의 heapq — 리스트 하나가 그대로 힙이 됩니다.
Python
브라우저에서 실행
🎮 힙 실험실
값을 넣으면 부모와 비교하며 위로 올라가고(sift-up), 꺼내면 맨 끝 값이 위로 갔다가 아래로 내려옵니다(sift-down). 한 걸음씩 눌러 확인해 보세요.
힙의 진짜 위력 — '전부 정렬하지 않고 상위 K개만'
Python
브라우저에서 실행
같은 우선순위일 때 먼저 넣은 것이 먼저 나오게 하는 요령.
Python
브라우저에서 실행
🤔 확인 문제
힙(최소 힙)이 반드시 지키는 규칙은?
해설 부모 ≤ 자식만 지키면 됩니다. 형제끼리는 규칙이 없어요. 그래서 전체가 정렬되어 있지 않은데도 맨 위는 언제나 최솟값입니다.
🤔 확인 문제
힙이 우선순위 큐에 알맞은 이유는?
해설 리스트로 하면 꺼낼 때마다 전부 훑어야 하고, 정렬을 유지하면 넣을 때마다 밀어내야 합니다. 힙은 둘 다 높이만큼이라 균형이 좋아요.
🤔 확인 문제
10만 개 중 상위 5개만 필요할 때 가장 효율적인 방법은?
해설 전체 정렬은 필요 없는 일까지 합니다. 크기 5짜리 힙이면 값 하나 볼 때마다 아주 조금만 일하고, 메모리도 5칸이면 돼요.