슬라이드 1

Similar documents
슬라이드 1

슬라이드 1

슬라이드 1

chap 5: Trees

슬라이드 1

Microsoft PowerPoint - 08-chap06-Queue.ppt

Microsoft PowerPoint - 08-Queue.ppt

o 경로 (path) 트리에서사용하는용어 ~ 어떤한노드에서다른노드까지링크를통해이동했을때, 거쳐온노드들의집합. o 루트 (root) ~ 트리의가장상위에있는노드로루트는항상하나만존재 o 부모, 자식 (parent, children) ~ 링크로연결된노드중위에있는노드를부모노드,

7장

Chapter 4. LISTS

슬라이드 1

chap 5: Trees

슬라이드 1

PowerPoint 프레젠테이션

Ch.1 Introduction

11강-힙정렬.ppt

e-비즈니스 전략 수립

슬라이드 1

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

06장.리스트

03_queue

11장 포인터

Microsoft PowerPoint - chap10_tree

리스트 (list), 선형리스트 (linear list): 순서를가진항목들의모임 집합 : 항목간의순서의개념이없음 L = n ( item0, item1,..., item -1) l 리스트의예 l 요일 : ( 일요일, 월요일,, 토요일 ) l 한글자음의모임 : ( ㄱ, ㄴ

Contents v 학습목표 자료구조큐에대한개념을스택과비교하여이해한다. 큐의특징과연산방법에대해알아본다. 순차표현방법을이용한큐와연결표현방법을이용한큐를구현해본다. 큐의응용방법을알아본다. v 내용 큐 큐의구현 큐의응용 2/74

Microsoft PowerPoint - lec07_tree [호환 모드]

1장. 리스트

입학사정관제도

슬라이드 1

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

Lab 3. 실습문제 (Single linked list)_해답.hwp

08장.트리

Lab 4. 실습문제 (Circular singly linked list)_해답.hwp

슬라이드 1

Chapter 4. LISTS

이번장에서학습할내용 동적메모리란? malloc() 와 calloc() 연결리스트 파일을이용하면보다많은데이터를유용하고지속적으로사용및관리할수있습니다. 2

슬라이드 1

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

원형연결리스트에대한설명중틀린것은 모든노드들이연결되어있다 마지막에삽입하기가간단한다 헤더노드를가질수있다 최종노드포인터가 NULL이다 리스트의 번째요소를가장빠르게찾을수있는구현방법은무엇인가 배열 단순연결리스트 원형연결리스트 이중연결리스트 단순연결리스트의노드포인터 가마지막노드를

제 11 장 다원 탐색 트리

o 스택 (stack) ~ 쌓아놓은더미 1. 스택의개요 - 2 -

C 언어 강의노트

슬라이드 1

슬라이드 1

05_tree

Microsoft PowerPoint - Chap5 [호환 모드]

K&R2 Reference Manual 번역본

03장.스택.key

슬라이드 1

untitled

Chap 6: Graphs

Chapter 4. LISTS

4.1 관계

02장.배열과 클래스

5.스택(강의자료).key

Microsoft PowerPoint - ch07 - 포인터 pm0415

<4D F736F F F696E74202D20C1A637C0E52DB0EDB1DEBFACB0E1B8AEBDBAC6AE2E >

슬라이드 1

Microsoft PowerPoint - 제4장-스택과큐.pptx

ABC 10장

Microsoft PowerPoint - 07-chap05-Stack.ppt

Microsoft PowerPoint - 제8장-트리.pptx

Lab 5. 실습문제 (Double linked list)-1_해답.hwp

쉽게 배우는 알고리즘 강의노트

Microsoft PowerPoint - 6장 탐색.pptx

슬라이드 1

6장정렬알고리즘.key

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Algorithms

untitled

untitled

Microsoft PowerPoint - 자료구조2008Chap06

Microsoft PowerPoint - 자료구조2008Chap07

슬라이드 1

제 11 장포인터 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

제 1 장 기본 개념

01장.자료구조와 알고리즘

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

09J1_ _R.hwp

Microsoft PowerPoint - Chap5 [호환 모드]

<4D F736F F F696E74202D20C1A63132B0AD20B5BFC0FB20B8DEB8F0B8AEC7D2B4E7>

PowerPoint 프레젠테이션

슬라이드 1

OCW_C언어 기초

Microsoft PowerPoint - ch08_큐 [호환 모드]

04장.큐

Microsoft PowerPoint - chap-11.pptx

chap01_time_complexity.key

설계란 무엇인가?

11장 포인터

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

Chapter 08. 트리(Tree)

Microsoft PowerPoint - 제11장 포인터(강의)

중간고사 (자료 구조)

Microsoft PowerPoint - chap11-포인터의활용.pptx

정의 이진탐색트리 이진탐색트리 (BST: binary search tree) 는각각의노드가 BST 특성을만족하는키 - 주소쌍을가지고있는이진트리 BST 특성 트리에있는각각의키에대해, 왼쪽서브트리에있는모든키는이것보다작고, 오른쪽서브트리에있는모든키는이것보다큼 < > 2

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C4C656D70656C2D5A69762E637070>

<4D F736F F F696E74202D20C1A63137C0E520B5BFC0FBB8DEB8F0B8AEBFCD20BFACB0E1B8AEBDBAC6AE>

Microsoft PowerPoint - 제11장 포인터

Transcription:

CHAP 8: 우선순위큐

우선순위큐 우선순위큐 (priority queue): 우선순위를가진항목들을저장하는큐 FIFO 순서가아니라우선순위가높은데이터가먼저나가게된다.

우선순위큐 가장일반적인큐 : 스택이나 FIFO 큐를우선순위큐로구현할수있다. 자료구조스택큐우선순위큐 삭제되는요소가장최근에들어온데이터가장먼저들어온데이터가장우선순위가높은데이터 응용분야 : 시뮬레이션시스템 ( 여기서의우선순위는대개사건의시각이다.) 네트워크트래픽제어 운영체제에서의작업스케쥴링

우선순위큐 ADT 객체 : n개의 element형의우선순위를가진요소들의모임 연산 : create() ::= 우선순위큐를생성한다. init(q) ::= 우선순위큐 q를초기화한다. is_empty(q) ::= 우선순위큐 q가비어있는지를검사한다. is_full(q) ::= 우선순위큐 q가가득찼는가를검사한다. insert(q, x) ::= 우선순위큐 q에요소 x를추가한다. delete(q) ::= 우선순위큐로부터가장우선순위가높은요소를삭제하고이요 소를반환한다. find(q) ::= 우선순위가가장높은요소를반환한다.

우선순위큐 ADT 가장중요한연산은 insert 연산 ( 요소삽입 ), delete 연산 ( 요소삭제 ) 이다. 우선순위큐는 2 가지로구분 최소우선순위큐 최대우선순위큐

우선순위큐구현방법 배열을이용한우선순위큐 연결리스트를이용한우선순위큐 히프 (heap) 를이용한우선순위큐

우선순위큐구현방법 표현 방법 삽 입 삭 제 순서없는배열 O(1) O(n) 순서없는연결리스트 O(1) O(n) 정렬된배열 O(n) O(1) 정렬된연결리스트 O(n) O(1) 히프 O(logn) O(logn)

히프 (heap) 란? 히프란노드들이저장하고있는키들이다음과같은식을만족하는완전이진트리 최대히프 (max heap) 부모노드의키값이자식노드의키값보다크거나같은완전이진트리 key( 부모노드 ) key( 자식노드 ) 최소히프 (min heap) 부모노드의키값이자식노드의키값보다작거나같은완전이진트리 key( 부모노드 ) key( 자식노드 )

히프의높이 n 개의노드를가지고있는히프의높이는 O(logn) 히프는완전이진트리 마지막레벨 h 을제외하고는각레벨 i 에 2 i-1 개의노드존재 깊이노드의개수 1 1=2 0 2 2=2 1 3 4=2 2 4 3

히프의구현방법 히프는배열을이용하여구현 완전이진트리이므로각노드에번호를붙일수있다 이번호를배열의인덱스라고생각 부모노드와자식노드를찾기가쉽다. 왼쪽자식의인덱스 = ( 부모의인덱스 )*2 오른쪽자식의인덱스 = ( 부모의인덱스 )*2 + 1 부모의인덱스 = ( 자식의인덱스 )/2

히프에서의삽입 히프에있어서삽입연산은회사에서신입사원이들어오면일단말단위치에앉힌다음에, 신입사원의능력을봐서위로승진시키는것과비숫 (1) 히프에새로운요소가들어오면, 일단새로운노드를히프의마지막노드에이어서삽입 (2) 삽입후에새로운노드를부모노드들과교환해서히프의성질을만족

upheap 연산 새로운키 k 의삽입연산후히프의성질이만족되지않을수있다 upheap 는삽입된노드로부터루트까지의경로에있는노드들을 k 와비교, 교환함으로써히프의성질을복원한다. 키 k 가부모노드보다작거나같으면 upheap 는종료한다 히프의높이가 O(logn) 이므로 upheap 연산은 O(logn) 이다.

upheap 알고리즘 insert_max_heap(a, key) heap_size heap_size + 1; i heap_size; A[i] key; while i 1 and A[i] > A[PARENT(i)] do A[i] A[PARENT]; i PARENT(i);

HeapType 정의 #include <stdio.h> #define MAX_ELEMENT 200 typedef struct { int key; element; typedef struct { element heap[max_element]; int heap_size; HeapType; // 초기화함수 init(heaptype *h) { h->heap_size =0;

삽입프로그램 // 현재요소의개수가 heap_size 인히프 h 에 item 을삽입한다. // 삽입함수 void insert_max_heap(heaptype *h, element item) { int i; i = ++(h->heap_size); // 트리를거슬러올라가면서부모노드와비교하는과정 while((i!= 1) && (item.key > h->heap[i/2].key)) { h->heap[i] = h->heap[i/2]; i /= 2; h->heap[i] = item; // 새로운노드를삽입

히프에서의삭제 최대히프에서의삭제는가장큰키값을가진노드를삭제하는것을의미 따라서루트노드가삭제된다. 삭제연산은회사에서사장의자리가비게되면먼저제일말단사원을사장자리로올린다음에, 능력에따라강등시키는것과비슷하다. (1) 루트노드를삭제한다 (2) 마지막노드를루트노드로이동한다. (1) 루트에서부터단말노드까지의경로에있는노드들을교환하여히프성질을만족시킨다.

downheap 알고리즘 히프의높이가 O(logn) 이므로 downheap 연산은 O(logn) 이다.

downheap 알고리즘 delete_max_heap(a) item A[1]; A[1] A[heap_size]; heap_size heap_size-1; i 2; // root의 left child, i 2*i while i heap_size do if i < heap_size and A[i+1] > A[i] then largest i+1; else largest i; if A[PARENT(largest)] > A[largest] then break; A[PARENT(largest)] A[largest]; i CHILD(largest); // i 2*i return item;

삭제프로그램 // 삭제함수 element delete_max_heap(heaptype *h) { int parent, child; element item, temp; item = h->heap[1]; temp = h->heap[(h->heap_size)--]; parent = 1; child = 2; while( child <= h->heap_size ) { // 현재노드의자식노드중더작은자식노드를찾는다. if( ( child < h->heap_size ) && (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;

전체프로그램 #include <stdio.h> #define MAX_ELEMENT 200 typedef struct { int key; element; typedef struct { element heap[max_element]; int heap_size; HeapType; // 초기화함수 init(heaptype *h) { h->heap_size =0;

전체프로그램 void main() { element e1={10, e2={5, e3={30; element e4, e5, e6; HeapType heap; // 히프생성 init(&heap); // 초기화 // 삽입 insert_max_heap(&heap, e1); insert_max_heap(&heap, e2); insert_max_heap(&heap, e3); // print_heap(&heap); // 삭제 e4 = delete_max_heap(&heap); printf("< %d > ", e4.key); e5 = delete_max_heap(&heap); printf("< %d > ", e5.key); e6 = delete_max_heap(&heap); printf("< %d > ", e6.key); < 30 > < 10 > < 5 >

히프의복잡도분석 삽입연산에서최악의경우, 루트노드까지올라가야하므로트리의높이에해당하는비교연산및이동연산이필요하다. O(log(n)) 삭제도최악의경우, 가장아래레벨까지내려가야하므로역시트리의높이만큼의시간이걸린다. O(log(n))

히프정렬 히프를이용하면정렬가능 먼저정렬해야할 n 개의요소들을최대히프에삽입 한번에하나씩요소를히프에서삭제하여저장하면된다. 삭제되는요소들은값이증가되는순서 ( 최소히프의경우 ) 하나의요소를히프에삽입하거나삭제할때시간이 O(log(n)) 만큼 소요되고요소의개수가 n 개이므로전체적으로 O(n*log(n)) 시간이걸린다. ( 빠른편 ) 히프정렬이최대로유용한경우는전체자료를정렬하는것이아니라가장큰값몇개만필요할때이다. 이렇게히프를사용하는정렬알고리즘을히프정렬이라고한다.

히프정렬프로그램 // 우선순위큐인히프를이용한정렬 void heap_sort(element a[], int n) { int i; HeapType h; init(&h); for(i=0;i<n;i++){ insert_max_heap(&h, a[i]); for(i=(n-1);i>=0;i--){ a[i] = delete_max_heap(&h);

이산이벤트시뮬레이션 이산이벤트시뮬레이션에서모든시간의진행은이벤트의발생에의해서 이루어진다. 우선순위큐를이용하여이벤트를저장하고이벤트의발생시각을 우선순위로하여이벤트를처리하는간단한시뮬레이션을작성하여보자.

이산이벤트시뮬레이션 #define ARRIVAL 1 #define ORDER 2 #define LEAVE 3 int free_seats=10; double profit=0.0; #define MAX_ELEMENT 100 typedef struct { int type; // 이벤트의종류 int key; // 이벤트가일어난시각 int number; // 고객의숫자 element; typedef struct { element heap[max_element]; int heap_size; HeapType;

이산이벤트시뮬레이션 // 초기화함수 void init(heaptype *h) { h->heap_size =0; // int is_empty(heaptype *h) { if( h->heap_size == 0 ) return TRUE; else return FALSE;

이산이벤트시뮬레이션 // 삽입함수 void insert_min_heap(heaptype *h, element item) { int i; i = ++(h->heap_size); // 트리를거슬러올라가면서부모노드와비교하는과정 while((i!= 1) && (item.key < h->heap[i/2].key)){ h->heap[i] = h->heap[i/2]; i /= 2; h->heap[i] = item; // 새로운노드를삽입

이산이벤트시뮬레이션 // 삭제함수 element delete_min_heap(heaptype *h) { int parent, child; element item, temp; item = h->heap[1]; temp = h->heap[(h->heap_size)--]; parent = 1; child = 2; while( child <= h->heap_size ){ if( ( child < h->heap_size ) && (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;

이산이벤트시뮬레이션 // 0에서 n사이의정수난수생성함수 int random(int n) { return rand() % n; // 자리가가능하면빈자리수를사람수만큼감소시킨다. int is_seat_available(int number) { printf("%d명의고객도착 \n", number); if( free_seats >= number ){ free_seats -= number; return TRUE; else { printf(" 자리가없어서떠남 \n"); return FALSE;

이산이벤트시뮬레이션 // 주문을받으면순익을나타내는변수를증가시킨다. void order(int scoops) { printf(" 아이스크림 %d개주문받음 \n", scoops); profit += 0.35 * scoops; // 고객이떠나면빈자리수를증가시킨다. void leave(int number) { printf("%d명이매장을떠남 \n", number); free_seats += number;

이산이벤트시뮬레이션 // 이벤트를처리한다. void process_event(heaptype *heap, element e) { int i=0; element new_event; printf(" 현재시간 =%d\n", e.key); switch(e.type){ case ARRIVAL: // 자리가가능하면주문이벤트를만든다. if( is_seat_available(e.number) ){ new_event.type=order; new_event.key = e.key + 1 + random(4); new_event.number=e.number; insert_min_heap(heap, new_event); break;

이산이벤트시뮬레이션 case ORDER: // 사람수만큼주문을받는다. for (i = 0; i < e.number; i++){ order(1 + random(3)); // 매장을떠나는이벤트를생성한다. new_event.type=leave; new_event.key = e.key + 1 + random(10); new_event.number=e.number; insert_min_heap(heap, new_event); break; case LEAVE: // 고객이떠나면빈자리수를증가시킨다. leave(e.number); break;

int main() { element event; HeapType heap; unsigned int t = 0; init(&heap); // 처음에몇개의초기이벤트를생성시킨다. while (t < 5) { t += random(6); event.type = ARRIVAL; event.key = t; event.number = 1 + random(4); insert_min_heap(&heap, event); while (!is_empty(&heap)) { event = delete_min_heap(&heap); process_event(&heap, event); printf(" 전체순이익은 =%f입니다.\n ", profit);

이산이벤트시뮬레이션 현재시간 = 0 3 명의고객도착현재시간 = 1 4 명의고객도착현재시간 = 4 아이스크림 1 개주문받음아이스크림 3 개주문받음아이스크림 3 개주문받음현재시간 = 4 아이스크림 1 개주문받음아이스크림 1 개주문받음아이스크림 1 개주문받음아이스크림 2 개주문받음현재시간 = 4 2 명의고객도착현재시간 = 5 아이스크림 3 개주문받음아이스크림 2 개주문받음현재시간 = 6 4 명의고객도착자리가없어서떠남현재시간 = 6 4 명이매장을떠남현재시간 = 7 2 명이매장을떠남현재시간 = 10 3 명이매장을떠남전체순이익은 = 5.950000 입니다.

허프만코드 이진트리는각글자의빈도가알려져있는메시지의내용을압축하는데사용될수있다. 이런종류의이진트리를허프만코딩트리라고부른다.

글자의빈도수 예를들어보자. 만약텍스트가 e, t, n, i, s 의 5 개의글자로만이루어졌다고가정하고각글자의빈도수가다음과같다고가정하자. 24

허프만코드생성절차

허프만코드프로그램 #define MAX_ELEMENT 100 typedef struct TreeNode { int weight; struct TreeNode *left_child; struct TreeNode *right_child; TreeNode; typedef struct { TreeNode *ptree; int key; element; typedef struct { element heap[max_element]; int heap_size; HeapType;

허프만코드프로그램 // 초기화함수 init(heaptype *h) { h->heap_size =0; // 삽입함수 void insert_min_heap(heaptype *h, element item) { // 프로그램 8.5 참조 // 삭제함수 element delete_min_heap(heaptype *h) { // 프로그램 8.5 참조

// 이진트리생성함수 TreeNode *make_tree(treenode *left, TreeNode *right) { TreeNode *node= (TreeNode *)malloc(sizeof(treenode)); if( node == NULL ){ fprintf(stderr," 메모리에러 \n"); exit(1); node->left_child = left; node->right_child = right; return node; // 이진트리제거함수 void destroy_tree(treenode *root) { if( root == NULL ) return; destroy_tree(root->left_child); destroy_tree(root->right_child); free(root);

허프만코드프로그램 // 허프만코드생성함수 void huffman_tree(int freq[], int n) { int i; TreeNode *node, *x; HeapType heap; element e, e1, e2; init(&heap); for(i=0;i<n;i++){ node = make_tree(null, NULL); e.key = node->weight = freq[i]; e.ptree = node; insert_min_heap(&heap, e);

허프만코드프로그램 for(i=1;i<n;i++){ // 최소값을가지는두개의노드를삭제 e1 = delete_min_heap(&heap); e2 = delete_min_heap(&heap); // 두개의노드를합친다. x = make_tree(e1.ptree, e2.ptree); e.key = x->weight = e1.key + e2.key; e.ptree = x; insert_min_heap(&heap, e); e = delete_min_heap(&heap); // 최종트리 destroy_tree(e.ptree);

허프만코드프로그램 // 주함수 void main() { int freq[] = { 15, 12, 8, 6, 4 ; huffman_tree(freq, 5);