public interface Heap<E> {
boolean isFull();
boolean isEmpty();
void levelOrder();
boolean add(E e);
E remove();
}
세부 구현
기본 필드
public class MaxHeap<E extends Comparable<E>> implements Heap<E>{
private static final int DEFAULT_CAPACITY = 1;
private static final int ROOT = 1;
private int size;
private int capacity;
private E[] heap;
@SuppressWarnings("unchecked")
public MaxHeap(int capacity) {
this.capacity = capacity;
this.heap = (E[]) new Comparable[capacity+1];
//ROOT 를 1로 설정할 것이기에 크기를 1 더
//E extends Comparable<E> 때문에 Object 가 아닌 Comparable
}
public MaxHeap() {
this(DEFAULT_CAPACITY);
}
ROOT의 인덱스를 1로 정의하겠습니다.
자식 & 부모 인덱스 구하기
//== 자식 & 부모 인덱스 반환 ==//
private int rightChildIdx(int parentIdx) {
return (parentIdx * 2) + 1;
}
private int leftChildIdx(int parentIdx) {
return parentIdx * 2;
}
private int parentIdx(int currentIdx) {
return currentIdx / 2;
}
public boolean add(E e) {
if (isFull()) grow();
size++;
heap[size] = e;//삽입하려는 노드를 가장 마지막에 추가
int currentIdx = size;
while (hasParent(currentIdx)) {//부모가 존재하는 경우 반복
int parentIdx = parentIdx(currentIdx);
E current = heap[currentIdx];
E parent = heap[parentIdx];
//== 부모가 더 크다면 Max Heap 만족 -> 반복 종료 ==//
if (parent.compareTo(current) >= 0) {break;}
//== 부모가 더 작다면 위치 변경 ==//
if (parent.compareTo(current) < 0) {swap(parentIdx, currentIdx);}
currentIdx = parentIdx;
}
return true;
}
1.부모 노드를 확인합니다. 만약존재하지 않는다면 반복을종료합니다. 2. 부모 노드가 존재한다면, 부모 노드보다작거나 같은 경우해당 위치가올바르게 삽입된 위치이므로 반복을종료합니다. 3. 만약 부모 노드보다큰 경우부모노드와위치를 바꾼 후다시 바꾼 위치의 부모 노드와비교하는 작업을반복합니다.
Heap에서 Root 제거
@Override
public E remove() {
E remove = heap[ROOT];
E last = heap[size];
heap[size] = null;
size--;
heap[ROOT] = last;
int currentIdx = ROOT;
while (hasChild(currentIdx)) {
//== 자식이 하나이거나 둘인 경우 -> 하나인 경우는 완전이진트리이므로 반드시 left Node 만 존재==//
int biggerChildIdx = biggerChildIdx(currentIdx);
E current = heap[currentIdx];
E child = heap[biggerChildIdx];
//== 자식보다 작은 경우에만 진행 ==//
if (current.compareTo(child) >= 0 ) {break;}
swap(biggerChildIdx, currentIdx);
currentIdx = biggerChildIdx;
}
return remove;
}
private int biggerChildIdx(int currentIdx) {
//== 호출되었을 때 반드시 child 는 존재하는 상황 ==//
//== 만약 Right Child가 존재하지 않는다면, Left Child가 자식 중 가장 큰 값 ==//
if (! hasRight(currentIdx)) return leftChildIdx(currentIdx);
//== rightChild가 leftChild보다 큰 경우 rightChild의 인덱스 반환 ==//
return (heap[rightChildIdx(currentIdx)].compareTo(heap[leftChildIdx(currentIdx)]) > 0)
? rightChildIdx(currentIdx)
: leftChildIdx(currentIdx);
}