본문 바로가기

Programming/Data Structure

Heap(힙) & Priority Queue(우선순위 큐)

힙(Heap)


힙은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리(Complete binary tree)


기본으로 한 자료구조(tree-based structure)로서 다음과 같은 힙 속성(property)을 만족한다.


::A가 B의 부모노드(parent node)이면, A의 키(key)값과 B의 키값 사이에는 대소관계가 성립한다::


힙에는 두 가지 종류가 있으며 부모노드의 키값이 자식노드의 키값보다 항상 큰 힙을 '최대 힙',


부모노드의 키값이 자식노드의 키값보다 항상 작은 힙을 '최소 힙'이라고 부른다.


키값의 대소관계는 오로지 부모노드와 자식노드 간에만 성립하며, 특히 형제 사이에는 대소관계가 정해지지 않는다.


각 노드의 자식노드의 최대개수는 힙의 종류에 따라 다르지만, 대부분의 경우는 자식노드의 개수가 최대 2개인


이진 힙(binary heap)을 사용한다.


힙에서는 가장 높은(혹은 낮은) 우선순위를 가지는 노드가 항상 뿌리노드에 오게 되는 특징이 있으며,


이를 응용하면 우선순위 큐와 같은 추상적 자료형을 구현할 수 있다.


*출처 : 위키백과



최소 힙(Min Heap)의 구현


최소 힙을 구현할때는 배열이 가장 좋고, 배열로 힙을 구현하면 힙의 마지막 노드의 위치를 빠르게 알 수 있고,


완전 이진 트리이므로 따로 링크를 보관하지 않아도 되는 등의 장점을 지니고 있다.


완전 이진 트리를 배열로 나타낼 때, 깊이 n의 노드는 배열의 {2^n-1} & {2^(n+1)-2} 번 요소에 저장을 하게 된다.


깊이 0의 루트 노드는 배열의 0번째 요소로 들어간다.


*참고 : http://blog.eairship.kr/249




우선순위 큐(Priority Queue)


컴퓨터 과학에서 우선순위 큐는 큐나 스택과 비슷한 축약 자료형이고, 각 원소들이 우선순위를 갖고 있다.


우선순위 큐에서 높은 우선순위를 가진 원소는 낮은 우선순위를 가진 원소보다 먼저 처리된다.


만약 두 원소가 같은 우선순위를 가진다면 그들은 큐에서 그들의 순서에 의해 처리된다.


1) 스택 : 원소들은 후입 선출 순으로 처리된다.

2) 큐 : 원소들은 선입 선출 순으로 처리된다.


우선순위 큐가 힙이라는 것은 널리 알려진 오류다. 우선순위 큐는 "list"나 "map"과 같은 추상적인 개념이다.


마치 list는 연결 리스트나 배열로 구현될 수 있는 것과 같이, 우선순위 큐는 힙이나 다른 방법을 이용해 구현될 수 있다.


우선순위 큐는 최소한 다음의 연산이 지원되어야 한다.


1) insert_with_priority : 하나의 원소를 우선순위를 지정해 큐에 추가한다.

2) pull_highest_priority_element : 가장 높은 우선순위를 가진 원소를 큐에서 제거하고 이를 반환한다.


*출처 : 위키백과


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include<iostream>
#include<queue>
 
using namespace std;
 
#define DEFAULT_SIZE 100001
 
template <typename T>
class Heap {
public:
    Heap();
    Heap(int);
    ~Heap();
    void insert(const T&);
    void swap(T* a, T* b);
    void print();
    T top();
    T pop();
private:
    T* heap;
    int capacity;
    int size;
};
 
template <typename T>
Heap<T>::Heap() {
    heap = new T[DEFAULT_SIZE];
    size = 0;
    capacity = DEFAULT_SIZE;
}
 
template <typename T>
Heap<T>::Heap(int Capacity) : capacity(Capacity)
{
    heap = new T[Heap::capacity];
    size = 0;
}
 
template <typename T>
Heap<T>::~Heap()
{
    delete[] heap;
}
 
template <typename T>
void Heap<T>::swap(T* a, T* b) {
    T temp = *a;
    *= *b;
    *= temp;
}
 
template <typename T>
void Heap<T>::insert(const T& data)
{
    int usedPos = size;
    int parentPos = (usedPos - 1/ 2;
 
    if (size == capacity)
    {
        cout << "Full Heap\n";
        return;
    }
 
    heap[size= data;
 
    while (usedPos >= 0 && heap[usedPos] < heap[parentPos]) {
        swap(&heap[usedPos], &heap[parentPos]);
        usedPos = parentPos;
        parentPos = (usedPos - 1/ 2;
    }
 
    size++;
}
 
template <typename T>
T Heap<T>::top() {
    if (size == 0return 0;
    else return heap[0];
}
 
template <typename T>
T Heap<T>::pop()
{
    if (size == 0return 0;
 
    int selectChild = 0;
    int parentPos = 0;
    int leftPos = 1;
    int rightPos = 2;
    T value = heap[0];
 
    size--;
    heap[0= NULL;
    swap(&heap[0], &heap[size]);
    while (1) {
        if (leftPos >= sizebreak;
        else if (rightPos >= size) selectChild = leftPos;
        else selectChild = heap[leftPos] > heap[rightPos] ? rightPos : leftPos;
 
        if (heap[selectChild] < heap[parentPos])
        {
            swap(&heap[parentPos], &heap[selectChild]);
            parentPos = selectChild;
        }
        else break;
 
        leftPos = 2 * parentPos + 1;
        rightPos = leftPos + 1;
    }
 
    return value;
}
 
 
template <typename T>
void Heap<T>::print()
{
    for (int i = 0; i < size; i++) {
        cout << heap[i] << " ";
    }
    cout << "\n";
}
 
int main() {
 
    int maxSize = 6;
    int input;
    Heap<int> heap(maxSize);
 
    for (int i = 0; i < maxSize; i++)
    {
        cin >> input;
        heap.insert(input);
    }
    heap.print();
 
    cout << heap.pop() << endl;
 
    heap.print();
 
    cout << heap.pop() << endl;
 
    heap.print();
 
    return 0;
}
cs


'Programming > Data Structure' 카테고리의 다른 글

Hash Table(해시 테이블)  (0) 2018.08.05
Linked List(연결 리스트)  (0) 2018.07.07