정의 : 완전 이진 트리의 일종으로 우선순위 큐를 위하여 만들어진 자료구조이다.
heap의 종류
Heap의 삽입
Heap의 삭제
import java.util.Arrays;
class MaxHeap {
private int[] heap;
private int maxSize = 10;
public MaxHeap() {
heap = new int[maxSize];
heap[0] = 0;
}
private int getParent(int index) {
return index / 2;
}
private int getLeftChild(int index) {
return index * 2;
}
private int getRightChild(int index) {
return index * 2 + 1;
}
private void swap(int index1, int index2) {
int temp = heap[index1];
heap[index1] = heap[index2];
heap[index2] = temp;
}
private int bigger(int index1, int index2) {
return heap[index1] > heap[index2] ? index1 : index2;
}
private void upHeapify() {
int rearIndex = heap[0];
while (rearIndex > 1 && heap[getParent(rearIndex)] < heap[rearIndex]) {
swap(rearIndex, getParent(rearIndex));
rearIndex /= 2;
}
}
private void downHeapify() {
int rootIndex = 1;
//왼쪽 자식의 존재는 조건에서 이미 존재하는 것으로 확인
while (rootIndex * 2 <= heap[0]) {
// 우측 자식이 존재 했을 경우
if (rootIndex * 2 + 1 <= heap[0]) {
// 좌측 우측 비교후 swap
int bigger = bigger(getLeftChild(rootIndex), getRightChild(rootIndex));
if (heap[rootIndex] >= heap[bigger]) {
break;
}
swap(rootIndex, bigger);
rootIndex = bigger;
} else { // 좌측 자식만 존재하는 경우
if (heap[rootIndex] >= heap[getLeftChild(rootIndex)]) {
break;
}
swap(rootIndex, getLeftChild(rootIndex));
rootIndex *= 2;
}
}
}
private void resize() {
maxSize *= 2;
int[] newHeap = Arrays.copyOf(heap, maxSize);
heap = newHeap;
}
public void add(int value) {
if (heap[0] + 1 >= maxSize) {
resize();
}
heap[++heap[0]] = value;
upHeapify();
}
public int extractRoot() {
int root = heap[1];
heap[1] = heap[heap[0]];
heap[heap[0]] = 0;
heap[0]--;
downHeapify();
return root;
}
public void printHeap() {
for (int i = 0; i < heap.length; i++) {
System.out.println("index = " + i + ", value = " + heap[i]);
}
}
}
import java.util.Arrays;
class MinHeap{
private int[] heap;
private int maxSize = 10;
public MinHeap(){
heap = new int[maxSize];
heap[0] = 0;
}
private int getParent(int index) {
return index/2;
}
private int getLeftChild(int index) {
return index * 2;
}
private int getRightChild(int index) {
return index * 2 + 1;
}
private void swap(int index1, int index2) {
int temp = heap[index1];
heap[index1] = heap[index2];
heap[index2] = temp;
}
private int smaller (int index1 ,int index2){
return heap[index1] < heap[index2] ? index1 : index2;
}
private void upHeapify() {
int rearIndex = heap[0];
while(rearIndex>1&&heap[getParent(rearIndex)]>=heap[rearIndex]){
swap(rearIndex,getParent(rearIndex));
rearIndex /= 2;
}
}
private void downHeapify() {
int rootIndex = 1;
//왼쪽 자식의 존재는 조건에서 이미 존재하는 것으로 확인 됨
while (rootIndex * 2 <= heap[0]) {
// 우측 자식이 존재 했을 경우
if (rootIndex * 2 + 1 <= heap[0]) {
// 좌측 우측 비교후 swap
int smaller = smaller(getLeftChild(rootIndex), getRightChild(rootIndex));
if(heap[rootIndex]<= heap[smaller]){
break;
}
swap(rootIndex,smaller);
rootIndex = smaller;
}else{ // 좌측 자식만 존재하는 경우
if (heap[rootIndex] <= heap[getLeftChild(rootIndex)]) {
break;
}
swap(rootIndex, getLeftChild(rootIndex));
rootIndex *= 2;
}
}
}
private void resize() {
maxSize *= 2;
int[] newHeap = Arrays.copyOf(heap, maxSize);
heap = newHeap;
}
public void add(int value) {
if(heap[0]+1 >= maxSize){
resize();
}
heap[++heap[0]] = value;
upHeapify();
}
public int extractRoot() {
int root = heap[1];
heap[1] = heap[heap[0]];
heap[heap[0]] = 0;
heap[0]--;
downHeapify();
return root;
}
public void printHeap() {
for (int i = 0; i < heap.length; i++) {
System.out.println("index = "+i+", value = "+heap[i]);
}
}
}
힙의 형태를 보면 최대 힙의 경우 루트가 항상 최댓값이고, 최소 힙의 경우 루트가 항상 최솟값이되기에 이 형질을 이용하여
우선순위 큐(priority queue) 구현시의 내부 자료구조
힙 정렬(heap sort)
에 사용 된다.
add() : O(log n)
extractRoot() : O(log n)