import java.util.ArrayList;
/**
* 최소 힙 기준으로 작성되었습니다.
* 배열로 작성해도 좋지만, ArrayList를 사용해서 크기를 유동적으로 가져갈 수 있게 구현했습니다.
*/
public class Heap {
ArrayList<Integer> heap;
public Heap() {
this.heap = new ArrayList<>();
this.heap.add(0); // 1번부터 시작할 예정이므로 0 삽입
}
// 데이터 삽입
public void push(int data) {
// 1. 트리의 가장 끝 위치에 데이터 삽입
heap.add(data);
int dataIdx = heap.size() - 1; // 삽입한 데이터의 위치
// 2. 부모 값과 비교 후, Heap 규칙에 맞지않으면 교환
while (dataIdx > 1 && heap.get(dataIdx / 2) > data) {
int parentVal = heap.get(dataIdx / 2);
heap.set(dataIdx / 2, data);
heap.set(dataIdx, parentVal);
dataIdx /= 2;
}
}
// 데이터 삭제
public Integer pop() {
// 힙이 비어있는 경우
if (heap.size() == 1) {
System.out.println("Heap is Empty");
return null;
}
// 루트 노드 반환
int returnVal = heap.get(1);
// 1. 루트 자리에 마지막 노드를 올리고 마지막 노드 삭제
heap.set(1, heap.remove(heap.size() - 1));
int curIdx = 1;
while (true) {
int leftIdx = curIdx * 2;
int rightIdx = curIdx * 2 + 1;
int targetIdx = -1;
if (rightIdx < heap.size()) { // 자식 노드가 둘인 경우
targetIdx = heap.get(leftIdx) < heap.get(rightIdx) ? leftIdx : rightIdx;
} else if (leftIdx < heap.size()) { // 자식이 하나인 경우
targetIdx = leftIdx;
} else {
break;
}
// 자식 노드와 부모 노드 값 비교
if (heap.get(curIdx) <= heap.get(targetIdx)) {
break;
} else { // 부모 노드가 자식 노드보다 크다면 교환
int parentVal = heap.get(curIdx);
heap.set(curIdx, heap.get(targetIdx));
heap.set(targetIdx, parentVal);
curIdx = targetIdx; // 이동한 노드 인덱스 갱신
}
}
return returnVal;
}
}