힙은 최댓값/최소값을 빠르게 찾아내기 위해 고안된 완전이진트리 자료구조이다. 힙은 최대/최소의 값을 검색하는데 O(1)
의 시간복잡도를 가진다. 이때 값을 얻기 위해 pop
을 하게 되면 O(logN)
의 시간이 걸린다. 또한 맨 처음 펼쳐진 N개의 값들을 힙에 세팅해 주어야 하므로 N
의 시간이 더 걸리게 된다. 그렇기 때문에 힙의 시간복잡도는 O(NlogN)
이라고 이야기 한다.
//max heap
export default class MyHeap {
constructor() {
this.heap = []; // n:parent, 2*n+1:left child, 2*n+2:right child
}
size() {
return this.heap.length;
}
push(node) {
this.heap.push(node);
let curIdx = this.heap.length - 1;
let parentIdx = Math.floor((curIdx - 1) / 2);
while (this.heap[parentIdx] < this.heap[curIdx]) {
[this.heap[parentIdx], this.heap[curIdx]] = [this.heap[curIdx], this.heap[parentIdx]];
curIdx = parentIdx;
parentIdx = Math.floor((curIdx - 1) / 2);
}
}
pop() {
const lastIdx = this.heap.length - 1;
let curIdx = 0;
[this.heap[curIdx], this.heap[lastIdx]] = [this.heap[lastIdx], this.heap[curIdx]];
const result = this.heap.pop();
while (curIdx < lastIdx) {
let leftIdx = curIdx * 2 + 1;
let rightIdx = curIdx * 2 + 2;
if (!this.heap[leftIdx]) break;
if (!this.heap[rightIdx]) {
if (this.heap[curIdx] < this.heap[leftIdx]) {
[this.heap[curIdx], this.heap[leftIdx]] = [this.heap[leftIdx], this.heap[curIdx]];
curIdx = leftIdx;
}
break;
}
if (this.heap[curIdx] < this.heap[leftIdx] || this.heap[curIdx] < this.heap[rightIdx]) {
const maxIdx = this.heap[leftIdx] > this.heap[rightIdx] ? leftIdx : rightIdx;
[this.heap[curIdx], this.heap[maxIdx]] = [this.heap[maxIdx], this.heap[curIdx]];
curIdx = maxIdx;
}
break;
}
return result;
}
}
부모 index * 2 + 1
(부모 index * 2) + 2
Math.floor(자식의 인덱스 - 1 / 2)
<aside> 💡 2를 나누고 math.floor로 소수점을 제외하면 같은 값이 나오는 수가 부모의 index이다.
</aside>
this.heap.length - 1
을 index로 사용하고 해당 index로 다시 heap에서 찾는 등 index와 index 값을 확실히 해야 한다.cur
이라고 정의할 것이 아닌 curIdx
등으로 index라는 것을 확실히 해야 나중에 헷갈리지 않는다.