C++/알고리즘

최대 힙 구현

그린티라떼 2021. 8. 30. 06:53

 

코드
#include <iostream>

using namespace std;

template<typename T>
class HEAP {
    int size;
    T *heapArr;
private:
    void pushSwap(int n){
        if( n ==1) return; //최상위 노드
        int parent = n /2 ;
        if(heapArr[parent] <heapArr[n]){ //부모노드보다 자식노드가 크면
            T tmp =heapArr[parent];
            heapArr[parent] = heapArr[n];
            heapArr[n] = tmp;

            pushSwap(parent);
        }
    }
    void popSwap(int n){
        int leftChild = (n * 2 <= size ? n * 2 : -1);
        int rightChild = (n * 2 + 1 <= size ? n * 2 + 1 : -1);
        int child; 
        //자식이 둘 다 없을 때
        if(leftChild == -1 && rightChild == -1 ) child = -1;
        //왼쪽 자식만 있을 때 (오른쪽만 있는 경우는 당연히 없다)
        else if (leftChild != -1 && rightChild == -1 ) child = leftChild ;
        //자식이 둘 다 있을 때
        else child = (heapArr[leftChild]> heapArr[rightChild] ? leftChild : rightChild) ;

        if(child == -1) return;
        if(heapArr[child] > heapArr[n]){ //자식이 더 크다면
            T tmp =heapArr[child];
            heapArr[child] = heapArr[n];
            heapArr[n] = tmp;

            popSwap(child);
        }
    }
public:
    HEAP(int n){
        size=0;
        heapArr =new int[n+1];
    }
    ~HEAP(){
        delete[] heapArr;
    }
    bool empty(){
        if(size == 0 ) return true;
        return false;
    }
    int amount(){
        return size;
    }
    T top(){
        return  empty() ? -1 : heapArr[1];
    }
    void push(int value){
        heapArr[++size]=value;
        pushSwap(size);
    }
    void pop(){
        if (empty())  // size ==0 이면 pop할 것이 없으니 return 
            return;
 
        heapArr[1] = heapArr[size--];
        popSwap(1);
    }
    void show(){
        for(int i =1 ; i< size+1 ; i++){
            cout<<heapArr[i]<<", ";
        }
        cout<<endl;
    }
};

최댓값을 구하기 위해 최악의 경우가 생겨도 힙은 완전 이진 트리이므로 항상 O(lgN)의 시간에 해결

주의점 : 최대힙은 요소의 삽입, 삭제 속에서 최댓값을 빠르게 찾아가는 과정이지, 내림차순으로 정렬 된 것이 아님을 알아야 한다.

 

 

최소 힙
int mian()
{
    HEAP<int> maxh(size);
    HEAP<int> minh(size);
    for (int i = 0; i < size; i++)
    {
        maxh.push(i);
        minh.push(i * -1);
    }
    maxh.show();
    minh.show();
}

결과 : maxh.show() :  9,  8,  5,  6,  7,  1,  4,  0,  3,  2,

          minh.show() : 0, -1, -2, -3, -4, -5, -6, -7, -8, -9,

최소 힙을 알기 위해서 -1를 곱해 주면 된다. minh.show() 결과에서 다시 -1를 곱해주면 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 가 되고 맨 앞에 있는 것이 최고 루트이므로 0이 최솟값이라는 것을 알 수 있다.

 

 

 

 

 


출처: https://www.crocus.co.kr/1184 [Crocus]