루트 노트(root node)는 항상 우선순위가 가장 높은 노드이다, 이러한 원리가 있어서 최대값과 최소값을 빠르게 찾을수 있으며 (시간 복잡도: O(1)) 삽입과 삭제시에도 부모와 자식노드간의 부모의 우선순위가 자식의 노드보다 높으면 되기때문에 (시간 복잡도: O(logN))의 빠르게 데이터를 삽입과 삭제를 할 수 있다.
힙에 새로운 요소가 들어오면 마지막 노드에 힙을 추가한다.
새로운 노드를 부모노드와 비교를 하여 힙의 성질을 만족시킨다.
일반적으로 힙은 두 가지의 타입을 가진다.
키 값의 대소관계는 항상 부모노드와 자식노드간의 관계에서만 성립하며, 형제 사이에는 대소관계가 성립 하지 않는다.
위에서 봐왔듯이 힙(heap)은 부모 노드의 인덱스를 알면 자식 노드의 인덱스를 알 수가 있다. 이러한 특징을 사용하여 heap을 구현해 보겠다.
class Minheap {
private ArrayList<Integer> heap;
public Minheap() {
heap = new ArrayList<>();
heap.add(0);
}
//힙 삽입
private void insert(int val) {
heap.add(val);
int pos = heap.size() - 1;
//루트 노드에 도달하거나, 부모노드가 자식노드보다 작아질 때 까지 반복
while (pos > 1 && heap.get(pos / 2) < heap.get(pos)) {
//swap
int tmp = heap.get(pos / 2);
heap.set(pos / 2, heap.get(pos));
heap.set(pos, tmp);
pos /= 2;
}
}
private int delete() {
if (heap.size() < 1) {
return 0;
}
int deleteData = heap.get(1); //루트 노드 삭제
//가장 아래에 있는 노드 루트 노드로
heap.set(1, heap.size() - 1);
//옮겨진 노드 삭제
heap.remove(heap.size() - 1);
int pos = 1;
while ((pos * 2) < heap.size()) {
int min = heap.get(pos * 2); //값
int minPos = pos * 2; //왼쪽 자식 인덱스
//왼쪽 자식과 오른쪽 자식값 비교
if ((pos * 2 + 1) < heap.size() && heap.get(pos * 2 + 1) > min) {
//오른쪽 값이 더크면 왼쪽이랑 바꿔준다.
min = heap.get(pos * 2 + 1);
minPos = pos * 2 + 1;
}
if (heap.get(pos) < min) break;
//swap
int tmp = heap.get(pos);
heap.set(pos, heap.get(minPos));
heap.set(minPos, tmp);
pos = minPos;
}
return deleteData;
}
}