우선순위 큐
2021. 6. 18. 21:25ㆍ자료구조
728x90
우선순위 큐
정의
우선순위를 가진 항목들을 저장하는 큐
FIFO 가 아닌 우선순위가 높은 데이터가 먼저 나감.
시뮬레이션 시스템
네트워크 트레픽 제어
운영체제의 작업 스케줄링
ADT
- create() : 우선순위 큐를 생성함
- init(q) : 우선순위 큐 q를 초기화 함
- is_empty(q) : 우선순위큐 q가 비었는지 검사함
- is_full(q) :우선순위큐 q가 가득 찼는지 검사함
- insert(q, x) : 우선순위큐 q에 요소 x 를 추가함
- delete(q) : 우선순위큐로부터 가장 우선순위가 높은 요소를 삭제함과 동시에 반환함
- find(q) : 우선순위가 가장 높은 요소를 반환함
종류
- 최대 우선순위 큐
- 최소 우선순위 큐
구현 방법
- 배열을 이용
- 연결리스트를 이용
- 힙을 이용
힙(heap)
노드의 키들이 다음 식을 만족하는 완전이진트리
key(부모노드) $$\geq$$ key(자식노드)
- 최대 힙
- 부모 노드의 키 값이 자식노드의 키 값보다 크거나 같은 완전 이진트리
- 최소 힙
- 부모 노드의 키값이 자식 노드의 키값보다 작거나 같은 완전 이진트리
- 힙의 높이
- $$n$$개의 노드를 가지고 있는 힙의 높이는 $$O(\log{n})$$
- 마지막 레벨을 제외하고, 각 레벨 $$i$$에 $$2^{i-1}$$개의 노드 존재
- 최대 힙
구현 방법
배열 : 완전 이진트리이므로 각 노드에 번호를 붙일 수 있으며, 번호를 인덱스라고 생각 함.
- 왼쪽 자식의 인덱스 : 부모의 인덱스 * 2
- 오른쪽 자식의 인덱스 : 부모의 인덱스 * 2 + 1
- 부모의 인덱스 : 자식의 인덱스 / 2
#define _CRT_SECURE_NO_WARININGS #define MAX_ELEMENT 200 #define PARENT(x) x/2 #include <stdio.h> #include <stdlib.h> typedef struct _key { int key; }element; typedef struct _heap { element heap[MAX_ELEMENT]; int heap_size; }Heap; Heap* create(void) { return (Heap*)malloc(sizeof(Heap)); } void init(Heap* h) { h->heap_size = 0; } void up_heap(Heap* h, element item) { int i = ++(h->heap_size); while (i != 1 && item.key > h->heap[PARENT(i)].key) { h->heap[i] = h->heap[PARENT(i)]; i = PARENT(i); } h->heap[i] = item; } void down_heap(Heap* h, element item) { int i = ++(h->heap_size); while (i != 1 && item.key < h->heap[PARENT(i)].key) { h->heap[i] = h->heap[PARENT(i)]; i = PARENT(i); } h->heap[i] = item; } element delete_heap(Heap* h, int is_up) { int parent = 1, child = 2; element item, temp; item = h->heap[1]; temp = h->heap[(h->heap_size)--]; if (is_up) { while (child <= h->heap_size) { if ((child < h->heap[child + 1].key) && (h->heap[child].key < h->heap[child + 1].key)) child++; if (temp.key >= h->heap[child].key) break; h->heap[parent] = h->heap[child]; parent = child; child *= 2; } } else { while (child <= h->heap_size) { if ((child < h->heap[child + 1].key) && (h->heap[child].key > h->heap[child + 1].key)) child++; if (temp.key <= h->heap[child].key) break; h->heap[parent] = h->heap[child]; parent = child; child *= 2; } } h->heap[parent] = temp; return item; } int main(void) { element e1 = { 10 }, e2 = { 5 }, e3 = { 30 }; element e4, e5, e6; Heap* heap; heap = create(); // 히프 생성 init(heap); // 초기화 // 삽입 down_heap(heap, e1); down_heap(heap, e2); down_heap(heap, e3); // 삭제 e4 = delete_heap(heap, 0); printf("< %d > ", e4.key); e5 = delete_heap(heap, 0); printf("< %d > ", e5.key); e6 = delete_heap(heap, 0); printf("< %d > \n", e6.key); free(heap); return 0; }
up_heap 방식과 down_heap 방식 모두 구현함.
두 경우는 input 방식과 delete 방식이 다르다.
따라서 input 함수의 경우는 분리하였고, delete_heap은 매개변수
is_up
에 의해 delete 방식이 달라진다.
힙 정렬 (Heap Sort)
먼저 정렬해야할 n개의 요소들을 최대 힙에 삽입
한번에 하나씩 요소를 힙에서 삭제하여 저장함. (내림차순)
먼저 정렬해야할 n개의 요소들을 최소 힙에 삽입
한번에 하나씩 요소를 힙에서 삭제하여 저장함. (오름차순)
시간복잡도는 ($$O(n \log{n})$$)임.
가장 유용한 경우 : 가장 큰 값 몇개만 필요할 때
#define _CRT_SECURE_NO_WARNINGS
#define PARENT(x) x/2
#define MAXSIZE 100
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int data;
}element;
typedef struct {
element heap[MAXSIZE];
int size;
}Heap;
Heap* create(void) {
return (Heap*)malloc(sizeof(Heap));
}
void init(Heap* h) {
h->size = 0;
}
void insert_up(Heap* h, element item) {
int i = ++(h->size);
while (i != 1 && item.data > h->heap[PARENT(i)].data) {
h->heap[i] = h->heap[PARENT(i)];
i = PARENT(i);
}
h->heap[i] = item;
}
element delete_heap(Heap* h) {
int parent = 1, child = 2;
element item, temp;
item = h->heap[1];
temp = h->heap[h->size--];
while (child <= h->size) {
if ((child < h->heap[child + 1].data) && (h->heap[child].data < h->heap[child + 1].data))
child++;
if (temp.data >= h->heap[child].data)
break;
h->heap[parent] = h->heap[child];
parent = child;
child *= 2;
}
h->heap[parent] = temp;
return item;
}
void asc(element* h, int size) {
Heap* space = create();
init(space);
for (int i = 0; i < size; i++) {
insert_up(space, h[i]);
}
for (int i = 0; i < size; i++) {
h[i] = delete_heap(space);
}
}
int main(void) {
element e[] = { 1,4,2,7,6,3,2,5 };
int size = sizeof(e) / sizeof(element);
asc(e, size);
for (int i = 0; i < size; i++) {
printf("%d ", e[i].data);
}
}
728x90
'자료구조' 카테고리의 다른 글
그래프 (0) | 2021.06.18 |
---|---|
트리 (0) | 2021.06.18 |
후위표기식 전환 (스택) 2 (0) | 2021.06.18 |
후위표기식 전환 (스택이용) 1 (0) | 2021.06.18 |
큐 (0) | 2021.06.18 |