힙 자료구조(Heap)는 이진 트리(Binary Tree)의 일종으로, 우선순위 큐(Priority Queue)를 구현하기 위해 자주 사용된다. 힙은 두 가지 주요 조건을 만족한다.
초기 힙
10
/ \
9 8
/ \
3 4
새 값 15 추가
10
/ \
9 8
/ \ /
3 4 15
15와 10 교환:
15
/ \
10 8
/ \ /
3 4 9
초기 힙
15
/ \
10 8
/ \ /
3 4 9
루트 노드 15 삭제
마지막 노드 9를 루트로 이동
9
/ \
10 8
/ \
3 4
9와 10 교환
10
/ \
9 8
/ \
3 4
import java.util.ArrayList;
public class MaxHeap {
private ArrayList<Integer> heap;
public MaxHeap() {
heap = new ArrayList<>();
}
// 값 삽입
public void insert(int value) {
heap.add(value);
heapifyUp(heap.size() - 1);
}
// 루트 노드 삭제
public int delete() {
if (heap.size() == 0) {
throw new IllegalStateException("Heap is empty");
}
if (heap.size() == 1) {
return heap.remove(0);
}
int rootValue = heap.get(0);
heap.set(0, heap.remove(heap.size() - 1)); // 마지막 노드를 루트로 이동
heapifyDown(0); // Heapify-Down
return rootValue;
}
// Heapify-Up (삽입 시 호출)
private void heapifyUp(int index) {
int parentIndex = (index - 1) / 2;
while (index > 0 && heap.get(index) > heap.get(parentIndex)) {
swap(index, parentIndex); // 현재 노드와 부모 노드 교환
index = parentIndex;
parentIndex = (index - 1) / 2;
}
}
// Heapify-Down (삭제 시 호출)
private void heapifyDown(int index) {
int leftChildIndex = 2 * index + 1;
int rightChildIndex = 2 * index + 2;
int largest = index;
// 왼쪽 자식 노드와 비교
if (leftChildIndex < heap.size() && heap.get(leftChildIndex) > heap.get(largest)) {
largest = leftChildIndex;
}
// 오른쪽 자식 노드와 비교
if (rightChildIndex < heap.size() && heap.get(rightChildIndex) > heap.get(largest)) {
largest = rightChildIndex;
}
// 부모와 자식 노드를 교환
if (largest != index) {
swap(index, largest);
heapifyDown(largest); // 재귀
}
}
// 두 노드의 값을 교환
private void swap(int i, int j) {
int temp = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, temp);
}
}