ํ(Heap)์ ํตํด ๊ตฌํ๋๋ฉฐ FIFO(First In First Out)์ธ Queue์๋ ๋ค๋ฅด๊ฒ ์ฐ์ ์์๊ฐ ๋์ ๋ฐ์ดํฐ๊ฐ ๋จผ์ ๋๊ฐ๋ ํํ์ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
์์ ์ด์งํธ๋ฆฌ๋ก ์ต๋๊ฐ, ์ต์๊ฐ ํ์์ด ๋น ๋ฅด๋ค
- ์ด์งํ์ํธ๋ฆฌ(BST)์๋ ๋ค๋ฅด๊ฒ ์ค๋ณต๋ ๊ฐ์ด ํ์ฉ๋๋ค
- ์ต๋ ํ(Max Heap): ๋ถ๋ชจ ๋ ธ๋์ ํค ๊ฐ์ด ์์ ๋ ธ๋๋ณด๋ค ํฌ๊ฑฐ๊ฐ ๊ฐ์ ์์ ์ด์งํธ๋ฆฌ
- ์ต์ ํ(Min Heap): ๋ถ๋ชจ ๋ ธ๋์ ํค ๊ฐ์ด ์์ ๋ ธ๋๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์์ ์ด์งํธ๋ฆฌ
> ํ์ ๋์ ๋ฐฐ์ด๋ก ๊ตฌํ๋๋ฉฐ ์์ ์ด์งํธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ idx๋ฅผ ๊ฐ๋๋ค
- idx 0์ root ๋ ธ๋๋ฅผ ์๋ฏธํ๋ค
- i๋ฒ์งธ ์ผ์ชฝ ์์ ๋ ธ๋์ idx: (i * 2) + 1
- i๋ฒ์งธ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋์ idx: (i * 2) + 2
- i๋ฒ์งธ ์์ ๋ ธ๋์ root ๋ ธ๋ idx: (i / 2)
- ์์ ์ฝ์ /์ญ์ : O(logn)
- ์์ ํ์: O(1)
// ํ์ ๋ฐ์ดํฐ ์ฝ์
_heap.push_back(data);
// ์ฝ์
๋ ๋ฐ์ดํฐ ์ถ์ถ
int now = static_cast<int>(_heap.size()) - 1;
// ๋ฃจํธ ๋
ธ๋๊น์ง
while (now > 0)
{
// ๋ถ๋ชจ ๋
ธ๋์ ๋น๊ตํด์ ๋ ์์ผ๋ฉด ํจ๋ฐฐ
int next = (now - 1) / 2;
if (max(_heap[now], _heap[next]))
break;
// ๋ฐ์ดํฐ ๊ต์ฒด
::swap(_heap[now], _heap[next]);
now = next;
}
- ํ ๊ตฌ์กฐ์ ๋ง๊ฒ ๋ฐฐ์ด์ ๊ฐ์ฅ ๋ง์ง๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ๋ค
- ์ดํ ๋ถ๋ชจ๋ ธ๋์ ๋น๊ตํด์ ๋ถ๋ชจ๋ ธ๋๋ณด๋ค ํฌ๋ค๋ฉด ๋ฐ์ดํฐ๋ฅผ ๊ณ์ํด์ ๊ต์ฒดํด๋๊ฐ๋ค.
์ผ๋ฐ์ ์ผ๋ก ์์ ์ด์งํธ๋ฆฌ์ ์ผ์ข ์ธ ํ์ผ๋ก ๊ตฌํ๋๋ฉฐ ์ฐ์ ์์๋ฅผ ๊ฐ์ง ์์๋ค๋ก ์ด๋ฃจ์ด์ ธ์๋ค.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
template<typename T, typename Container = vector<T>, typename Predicate = less<T>>
class PriorityQueue
{
public:
void push(const T& data)
{
// ์ฐ์ ํ ๊ตฌ์กฐ๋ถํฐ ๋ง์ถฐ์ค๋ค
_heap.push_back(data);
// ๋์ฅ๊นจ๊ธฐ ์์
int now = static_cast<int>(_heap.size()) - 1;
// ๋ฃจํธ ๋
ธ๋๊น์ง
while (now > 0)
{
// ๋ถ๋ชจ ๋
ธ๋์ ๋น๊ตํด์ ๋ ์์ผ๋ฉด ํจ๋ฐฐ
int next = (now - 1) / 2;
if (_predicate(_heap[now], _heap[next]))
break;
// ๋ฐ์ดํฐ ๊ต์ฒด
::swap(_heap[now], _heap[next]);
now = next;
}
}
void pop()
{
_heap[0] = _heap.back();
_heap.pop_back();
int now = 0;
while (true)
{
int left = 2 * now + 1;
int right = 2 * now + 2;
// ๋ฆฌํ์ ๋๋ฌํ ๊ฒฝ์ฐ
if (left >= (int)_heap.size())
break;
int next = now;
// ์ผ์ชฝ๊ณผ ๋น๊ต
if (_predicate(_heap[next], _heap[left]))
next = left;
// ๋ ์ค ์น์๋ฅผ ์ค๋ฅธ์ชฝ๊ณผ ๋น๊ต
if (right < (int)_heap.size() && _predicate(_heap[next], _heap[right]))
next = right;
// ์ผ์ชฝ/์ค๋ฅธ์ชฝ ๋ ๋ค ํ์ฌ ๊ฐ๋ณด๋ค ์์ผ๋ฉด ์ข
๋ฃ
if (next == now)
break;
::swap(_heap[now], _heap[next]);
now = next;
}
}
T& top()
{
return _heap[0];
}
bool empty()
{
return _heap.empty();
}
private:
Container _heap = {};
Predicate _predicate = {};
};
int main()
{
PriorityQueue<int, vector<int>, greater<int>> pq;
pq.push(100);
pq.push(300);
pq.push(200);
pq.push(500);
pq.push(400);
while (pq.empty() == false)
{
int value = pq.top();
pq.pop();
cout << value << endl;
}
}