우선순위 큐는 Heap의 구조를 이용해 정렬을 수행하는 이진 트리 구조이다. Heap은 원소를 삽입시 가장 큰 원소가 루트 노드에 오도록 노드의 위치를 재배열한다. 이 재배열을 하는 과정은 매번 O(logn)의 시간복잡도를 가지게 된다.
우선순위 큐를 구현하면서 가장 큰 두가지의 기능인 Push와 Pop의 기능을 생각해보자. Push 연산을 하게 되면 원소는 가장 마지막 Leaf노드의 다음 위치에 삽입되게 된다. 다음 위치에 삽입된 후 부모 노드의 크기 값과 비교하여 만약 부모원소보다 크다면 자리를 바꾸고 이 과정을 반복해 나가게 된다. 결국 가장 큰 원소라면 루트 노드에 위치하게 될 것이고 pop할시 루트 노드의 값을 출력해주기만 하면 된다.
pop한뒤 남아 있는 원소들의 정렬에 대해서는 가장 마지막에 위치하는 리프노드의 값을 루트노드로 옮기고 자식노드 들과 비교하여 자식노드가 더 크다면 위치를 바꾸어 준다. 자식이 두개 존재하는 경우 왼쪽, 오른쪽 둘 중 더 큰 자식과 자리를 바꾸어준다.
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 147 148 149 150 #include <cstdio> #include <stdlib.h> using namespace std ;class PriorityQueue { private : int max_size = 10 ; int size = 0 ; void allocate () { arr = (int *)malloc ( sizeof (int ) * max_size ); } public : int * arr; PriorityQueue() { allocate(); } PriorityQueue(int size) { max_size = size; allocate(); } int getLeft (int n) { if (2 * n + 1 < size) return 2 * n + 1 ; else return -1 ; } int getRight (int n) { if (2 * n + 2 < size) return 2 * n + 2 ; else return -1 ; } int getParent (int n) { return (n - 1 ) / 2 ; } bool isFull () { return size == max_size; } bool isEmpty () { return size == 0 ; } void push (int a) { if (!isFull()) { int current = size; int parent = getParent(current); arr[current] = a; while (arr[current] > arr[parent]) { int temp = arr[current]; arr[current] = arr[parent]; arr[parent] = temp; current = parent; parent = getParent(current); } size++; } } int pop () { int target = arr[0 ]; arr[0 ] = arr[--size]; int current = 0 ; while (true ) { int left_child = getLeft(current); int right_child = getRight(current); if (left_child != -1 && right_child != -1 ) { if (arr[current] < arr[left_child] || arr[current] < arr[right_child]) { if (arr[left_child] < arr[right_child]) { int temp = arr[current]; arr[current] = arr[right_child]; arr[right_child] = temp; current = right_child; } else { int temp = arr[current]; arr[current] = arr[left_child]; arr[left_child] = temp; current = left_child; } } else break ; } else if (left_child != -1 ) { if (arr[current] < arr[left_child]) { int temp = arr[current]; arr[current] = arr[left_child]; arr[left_child] = temp; current = left_child; } else break ; } else { break ; } } return target; } }; void main () { PriorityQueue pq; pq.push(324 ); pq.push(532 ); pq.push(3 ); pq.push(1023 ); pq.push(84 ); pq.push(23 ); pq.push(5 ); while (!pq.isEmpty()) { printf ("%d " , pq.pop()); } }