본문 바로가기
Study/알고리즘

Max-Heap 알고리즘

by 이미뇨 2024. 7. 12.

1.기본개념

  • Max-Heap은 이진 트리의 일종으로, 부모 노드가 자식 노드보다 항상 크거나 같은 값을 가지는 특성을 가짐
  • Max-Heap의 규칙:
    • 완전 이진 트리(Complete Binary Tree): 마지막 레벨을 제외한 모든 레벨이 완전히 채워져 있으며, 마지막 레벨은 왼쪽에서 오른쪽으로 채워짐
    • 부모 노드의 값이 자식 노드의 값보다 크거나 같음

Max-Heap 배열로 표현

인덱스 i의 노드는 다음과 같은 자식 노드와 부모 노드의 관계를 가짐

  • 왼쪽 자식 노드: 2i + 1
  • 오른쪽 자식 노드: 2i + 2
  • 부모 노드: (i - 1) // 2 ( // : 정수 나눗셈 연산자 - 소수점 이하를 버리고 정수 부분만을 반환)

Index: 0 1 2 3 4 5 6 7 8
Array: [20, 15, 18, 8, 10, 5, 7, 3, 6]

이진 트리 표현

         20 (0)
        /     \
     15 (1)  18 (2)
     /  \    /  \
  8 (3) 10(4) 5 (5) 7 (6)
  /  \
3 (7) 6 (8)

 

완전 이진 트리와 Max-Heap의 관계

Max-Heap은 완전 이진 트리의 특성을 가지고 있으므로, 모든 노드가 왼쪽에서 오른쪽으로 순차적으로 채워짐. 이를 통해 힙의 효율적인 삽입과 삭제 연산이 가능! 완전 이진 트리는 배열로 쉽게 표현할 수 있어 힙을 배열로 구현하는 데 유리.

구현

 

class MaxHeap {
    constructor() {
        this.heap = [];
    }

    insert(val) {
        this.heap.push(val);
        this._siftUp(this.heap.length - 1);
    }

    deleteMax() {
        if (this.heap.length === 0) return null;
        if (this.heap.length === 1) return this.heap.pop();

        const maxVal = this.heap[0];
        this.heap[0] = this.heap.pop();
        this._siftDown(0);
        return maxVal;
    }

    _siftUp(index) {
        let parent = Math.floor((index - 1) / 2);
        while (index > 0 && this.heap[index] > this.heap[parent]) {
            [this.heap[index], this.heap[parent]] = [this.heap[parent], this.heap[index]];
            index = parent;
            parent = Math.floor((index - 1) / 2);
        }
    }

    _siftDown(index) {
        let largest = index;
        const left = 2 * index + 1;
        const right = 2 * index + 2;

        if (left < this.heap.length && this.heap[left] > this.heap[largest]) {
            largest = left;
        }
        if (right < this.heap.length && this.heap[right] > this.heap[largest]) {
            largest = right;
        }
        if (largest !== index) {
            [this.heap[index], this.heap[largest]] = [this.heap[largest], this.heap[index]];
            this._siftDown(largest);
        }
    }
}

 

insert(val): 새로운 값을 힙에 추가하고 _siftUp을 호출하여 힙 속성을 유지
_siftUp(index): 삽입된 값을 부모 노드와 비교하여 힙 속성이 유지되도록 위로 이동시킴
deleteMax(): 힙의 최대 값을 제거하고 마지막 원소를 루트로 이동시킨 후 _siftDown을 호출하여 힙 속성을 유지
_siftDown(index): 루트 값을 자식 노드와 비교하여 힙 속성이 유지되도록 아래로 이동시킴

예시문제

주어진 배열 [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]을 Max-Heap으로 변환하고, 최대 값을 제거한 후의 힙 상태를 출력하세요.

 

const heap = new MaxHeap();
const arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];

// 배열의 모든 값을 힙에 삽입
arr.forEach(num => heap.insert(num));

console.log("Max-Heap:", heap.heap);

// 최대 값 제거
const maxVal = heap.deleteMax();
console.log("Removed Max Value:", maxVal);
console.log("Heap after removing max value:", heap.heap);

 

출력

Max-Heap: [ 9, 6, 5, 5, 5, 4, 2, 1, 3, 1, 3 ]
Removed Max Value: 9
Heap after removing max value: [ 6, 5, 5, 3, 5, 4, 2, 1, 3, 1 ]

결론

Max-Heap은 우선순위 큐와 힙 정렬을 구현하는 데 필수적인 자료구조이다. 삽입과 삭제 연산이 효율적이며, 완전 이진 트리의 특성을 가지므로 배열을 이용한 구현이 용이하다.

'Study > 알고리즘' 카테고리의 다른 글

다익스트라 알고리즘  (0) 2024.07.12