힙
완전이진트리의 일종으로 우선순위 큐를 우하여 만들어진 자료구조
최댓값이나 최솟값을 빠르게 찾아내도록 만들어진 구조
완전이진트리 - 노드를 삽입할때 왼쪽부터 차례대로 삽입하는 트리
최대 힙 | 최소 힙 |
![]() |
![]() |
부모 노드의 키 값이 자식 노드의 키 값보다 크거나 같은 완전이진트리 | 부모 노드의 키 값이 자식 노드의 키 값보다 작거나 같은 완전이진트리 |
완전이진트리는 배열로 구현한다.
필자는 배열이 재할당을 알아서 해주기위해 vector를 사용
또한 이 코드는 최대 힙으로 구현
#include <iostream>
#include <vector>
using namespace std;
class Heap
{
int size = 0;
vector<int> heap;
public:
void push(int value)
{
heap.push_back(value);
sort(size);
size++;
}
void sort(int _size)
{
int c = _size;
int p = (c - 1) / 2;
while (c > 0 && heap[c] > heap[p])
{
swap(c, p);
c = p;
p = (c - 1) / 2;
}
}
void swap(int a, int b) {
int temp = heap[a];
heap[a] = heap[b];
heap[b] = temp;
}
int pop()
{
if (size == 0)
{
cout << "비어있습니다." << endl;
return 0;
}
int poll = heap[0];
heap[0] = heap[--size];
popsort();
return poll;
}
void popsort()
{
int p = 0;
int c = 1;
while(c <= size) {
if(c < size && heap[c] < heap[c + 1])
c++;
if(heap[c] <= heap[p]) break;
swap(c, p);
p = c;
c = c * 2 + 1;
}
}
void print()
{
for(int i=0; i<heap.size(); i++)
cout << heap[i] << " ";
cout << endl;
}
};
int main()
{
Heap h;
h.push(1);
h.push(10);
h.push(2);
h.push(6);
h.push(3);
h.push(7);
h.push(5);
h.push(6);
h.push(8);
h.print();
cout << "pop: " << h.pop() << endl;
h.print();
}
특정 노드의 배열 인덱스가 current라고 한다면
index가 1부터 시작할때)
부모노드 = current
좌측자식노드 = current * 2
우측자식노드 = current * 2 + 1
편리성을위해 이진트리 구현할때 보통 index는 1부터 시작하지만 필자는, 위에서 구현한 코드는 0 부터 사용하였다.
index가 0부터 시작할때)
부모노드 = current - 1
좌측자식노드 = current * 2 + 1
우측자식노드 = current * 2 + 2
힙 삽입 과정 O(log N)
1. 인덱스 순으로 가장 마지막 위치에 삽입
2. 부모 노드 6 < 삽입노드 8 이므로 서로 교환
3. 부모노드 6 < 삽입노드 8 이므도 서로 교환
4. 부모노드 10 > 삽입노드 8 이므로 더 이상 교환하지않는다.
힙 삭제 과정 O(log N)
1. 힙에서 삭제는 루트노드가 삭제된다
2. 삭제된 루트노드에 힙의 마지막 노드를 가져온다.
3. 가져온 루트노드와 자식노드중 더 큰 자식노드와 교환한다.
4. c 가 size보다 커지거나 (마지막 레벨이거나) 자식노드들 보다 클때까지 반복한다.