01. 우선순위큐 -...

28
01. 우선순위 큐 02. 03. 힙을 이용한 우선순위 큐의 구현 04. 선택 알고리즘

Upload: lyquynh

Post on 17-Sep-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

01. 우선순위 큐02. 힙

03. 힙을 이용한 우선순위 큐의 구현04. 선택 알고리즘

우선순위 큐(priority queue)◦ 우선순위를 가진 항목들을 저장하는 큐◦ FIFO 순서가 아니라 우선 순위가 높은 데이터가 먼저 인출

◦ 가장 일반적인 큐: 스택이나 FIFO 큐를 우선순위 큐로 구현 가능

자료구조 삭제되는 요소

스택 가장 최근에 들어온 데이터

큐 가장 먼저 들어온 데이터

우선순위큐 가장 우선순위가 높은 데이터

응용분야: 시뮬레이션 시스템(여기서의 우

선 순위는 대개 사건의 시각이다.)

네트워크 트래픽 제어 운영 체제에서의 작업 스케쥴링

보통의 큐처럼 동작하지만 “우선순위” 속성을 갖는 데이터를다룬다

삽입 연산

제거 연산

2 17 22 23 56 117

Front Rear

2 17 22 23 56 117

20

2 17 22 23 56 117

Dequeue

17 22 23 56 117

Front

가장 중요한 연산은 insert 연산(요소 삽입), delete 연산(요소 삭제)이다.

우선 순위 큐는 2가지로 구분

◦ 최소 우선 순위큐

◦ 최대 우선 순위큐

∙객체: n개의 element형의 우선 순위를 가진 요소들의 모임

∙연산:

▪ create() ::= 우선 순위큐를 생성한다.

▪ init(q) ::= 우선 순위큐 q를 초기화한다.

▪ is_empty(q) ::= 우선 순위큐 q가 비어있는지를 검사한다.

▪ is_full(q) ::= 우선 순위큐 q가 가득 찼는가를 검사한다.

▪ insert(q, x) ::= 우선 순위큐 q에 요소 x를 추가한다.

▪ delete(q) ::= 우선 순위큐로부터 가장 우선순위가 높은 요소를 삭제하고 이 요소를 반환한다.

▪ find(q) ::= 우선 순위가 가장 높은 요소를 반환한다.

배열을 이용한 우선순위큐

연결리스트를 이용한 우선순위큐

히프(heap)를 이용한 우선순위큐

표현 방법 삽 입 삭 제

순서없는 배열 O(1) O(n)

순서없는 연결 리스트 O(1) O(n)

정렬된 배열 O(n) O(1)

정렬된 연결 리스트 O(n) O(1)

히프 O(logn) O(logn)

노드들이 저장하고 있는 키들이 다음의 조건을 만족하는완전이진트리

최대 히프(max heap)◦ 부모 노드의 키값이 자식 노드의 키값보다 크거나 같은 완전 이진 트리

◦ key(부모노드) ≥key(자식노드)

최소 히프(min heap)◦ 부모 노드의 키값이 자식 노드의 키값보다 작거나 같은 완전 이진 트리

◦ key(부모노드) ≤key(자식노드)

힙 순서 속성(Heap Order Property)을 만족하는 완전 이진 트리

힙 순서 속성 : ◦ 트리 내의 모든 자식 노드가 부모 노드보다 커거나(최소 힙) 또는 모든 자식 노드가부모 노드보다 작아야 한다(최대 힙)

“힙에서 가장 작은 데이터를 갖는 노드는 루트 노드이다.”

8

67 161

2

13

52

17 43 88

37

힙에 있어서 삽입 연산은 회사에서 신입 사원이 들어오면 일단 말단 위치에 앉힌 다음에, 신입 사원의 능력을 봐서 위로 승진시키는 것과 비숫

(1)히프에 새로운 요소가들어 오면, 일단 새로운노드를 히프의 마지막 노드에 이어서 삽입

(2)삽입 후에 새로운 노드를 부모 노드들과 교환해서 히프의 성질을 만족

힙의 삽입 연산 : 최소 힙

1. 힙의 가장 최고 깊이, 최 우측에 새 노드를 추가한다 힙이완전 이진 트리를 유지하도록 함

2. 삽입한 노드를 부모 노드와 비교한다. 삽입한 노드가 부모 노드보다 크면 제 위치에 삽입된 것이므로 연산을 종료한다. 하지만 부모 노드보다 작으면 다음 단계를 진행한다.

3. 삽입한 노드가 부모 노드보다 작으면 부모 노드와 삽입한 노드의 위치를 서로 바꾼다. 위치를 바꾼 후에 단계 2.를 다시진행한다.

삽입 연산의 예 : 최소 힙의 경우

8

67 161

2

13

52

17 43 88

37

8

67 161

2

13

52

17 43 88 7

37

8

67 161

2

13

52

17 43 88 37

7

7

67 161

2

13

52

17 43 88 37

8

새로운 키 k의 삽입 연산후 힙의 성질이 만족되지 않을 수 있다

upheap는 삽입된 노드로부터 루트까지의 경로에 있는 노드들을 k와 비교, 교환함으로써힙의 성질을 복원한다.

키 k가 부모 노드보다 작거나 같으면upheap는 종료한다

히프의 높이가 O(logn)이므로 upheap연산은 O(logn)이다.

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);

최대히프에서의 삭제는 가장 큰 키값을 가진 노드를 삭제하는 것을 의미

-> 따라서 루트노드가 삭제된다.

삭제 연산은 회사에서 사장의 자리가 비게 되면 먼저 제일 말단 사원을 사장자리로 올린 다음에, 능력에 따라 강등시키는 것과 비숫하다.

(1)루트노드를 삭제한다(2)마지막노드를 루트노드

로 이동한다.(3)루트에서부터 단말노드

까지의 경로에 있는 노드들을 교환하여 히프 성질을 만족시킨다.

최소 힙의 삭제 연산◦ 루트 노드가 최소값 노드이므로 루트 노드를 삭제◦ 루트 노드를 삭제한 후 힙 순서 속성을 유지시키는 것이 삭제 연산의 관건.

1. 힙의 루트에 최고 깊이, 최 우측에 있던 노드를 루트 노드로옮겨온다 힙이 완전이진트리를유지하는 반면에 힙 순서속성이 파괴된다 이를 복원하기 위한 작업을 다음 단계에서부터 시작한다.

2. 옮겨온 노드의 양쪽 자식을 비교하여 작은 쪽 자식과 위치 교환을 한다. 힙 순서 속성이 지켜지려면 부모 노드는 양쪽 자식보다 작은 값을 가져야 하기 때문이다.

3. 옮겨온 노드가 더 이상 자식이 없는 잎노드가 되거나 양쪽 자식보다 작은 값을 갖는 경우에는 삭제 연산을 종료한다. 그렇지 않은 경우에는 단계 2를 반복한다.

최소값 삭제 연산의 예

7

67 161

2

13

52

17 43 88 37

8

7

67 161

37

13

52

17 43 88

8

37

67 161

7

13

52

17 43 88

8

8

67 161

7

13

52

17 43 88

37

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

delete_max_heap(A)

item ← A[1];

A[1] ← A[heap_size];

heap_size←heap_size-1;

i ← 2;

while i ≤ heap_size do

if i < heap_size and A[LEFT(i)] > A[RIGHT(i)]

then largest ← LEFT(i);

else largest ← RIGHT(i);

if A[PARENT(largest)] > A[largest]

then break;

A[PARENT(largest)] ↔ A[largest];

i ← CHILD(largest);

return item;

히프는 배열을 이용하여 구현

◦ 완전이진트리이므로 각 노드에 번호를 붙일 수 있다

◦ 이 번호를 배열의 인덱스라고 생각

부모 노드와 자식 노드를 찾기가 쉽다.

◦ 왼쪽 자식의 인덱스 = (부모의 인덱스)*2

◦ 오른쪽 자식의 인덱스 = (부모의 인덱스)*2 + 1

◦ 부모의 인덱스 = (자식의 인덱스)/2

배열을 이용한 힙의 구현

◦ 깊이 0의 노드는 배열의 0번 요소에 저장.

◦ 깊이 1의 노드(모두 2개)는 배열의 1~2번 요소에 저장.

◦ 깊이 2의 노드(모두 4개)는 배열의 3~6번 요소에 저장.

◦ “깊이 n의 노드(2n개)는배열의 2n+1 ~ 2n+1 –2 번 요소에 저장.”

2

0

7

1

52

2

13

3

8

4

67

5

161

6

17

7

43

8

88

9

6713

17 43

8

37

10

7

161

2

52

88 37

깊이 1 깊이 2 깊이 3깊이 0

깊이 1

깊이 2

깊이 3

깊이 0

n개의 노드를 가지고 있는 히프의 높이는 O(logn) ◦ 히프는 완전이진트리

◦ 마지막 레벨 h을 제외하고는 각 레벨 i에 2i-1개의 노드 존재

깊이 노드의 개수

1 1=20

2 2=21

3 4=22

4 3

힙을 사용하되,

노드 구조체에 Priority 필드를 추가하고

힙 순서 속성을 이 Priority 필드를 기준으로 맞춘다.

힙를 이용하면 데이터 정렬 가능

먼저 정렬해야 할 n개의 요소들을 최대 힙에 삽입 한번에 하나씩 요소를 힙에서 삭제하여 저장◦ 삭제되는 요소들은 값이 증가되는 순서(최소 힙의 경우)

정렬 성능◦ 하나의 요소를 힙에 삽입하거나 삭제할 때 시간이 O(logn) 만큼 소요되고 요소의 개수가 n개이므로 전체적으로O(nlogn)시간이 걸린다(빠른편)

히프 정렬이 유용한 경우◦ 전체 자료를 정렬하는 것이 아니라 가장 큰 값 몇 개만 필요할 때

// 우선 순위 큐인 히프를 이용한 정렬

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);

}

}

선택(Selection) 문제◦ N개의 원소로 이루어진 집합에서 i-번째 작은 원소를 찾는문제

◦ 예) 최대값 원소 또는 최소값 원소 찾기, 중간값 찾기

선택 알고리즘◦ 정렬(Sorting) 기반 접근법

퀵(Quick) 정렬을 이용하여 모든 원소들을 정렬한 후에i-번째 원소를 선택

O(nlogn) 시간 요구◦ 분할(Partition) 알고리즘 기반의 재귀적 접근법

퀵 정렬의 분할 알고리즘 기반으로 비교 집합을 축소시켜나가는 재귀적 접근법

평균 선형 시간 O(n) 요구

최악의 경우, O(n2) 시간 요구

분할 알고리즘 기반의 재귀적 접근법◦ 주어진 집합에 대해 분할 알고리즘을 적용하여 피봇 원소의순서값 k을 찾는다.

◦ k==i이면 k-번째 원소(피봇 원소)를 반환

◦ i < k 이면, 왼쪽 원소그룹에 대해 선택 알고리즘 실행

◦ i > k 이면, 오른쪽 원소그룹에 대해 선택 알고리즘 실행

분할 알고리즘 기반의 재귀적 접근법◦ 예 #1: 다음의 10개 원소로 이루어진 배열에서 2번째 작은원소를 찾아라.

31 8 48 73 11 3 20 29 65 15

p r

8 11 3 15 31 48 20 29 65 73

분할k

8 11 3

왼쪽 그룹에서 2번째 작은 원소를 찾는다

분할 알고리즘 기반의 재귀적 접근법◦ 예 #2: 다음의 10개 원소로 이루어진 배열에서 7번째 작은원소를 찾아라.

31 8 48 73 11 3 20 29 65 15

p r

8 11 3 15 31 48 20 29 65 73

분할k

31 48 20 29 65 73

오른쪽 그룹에서 3번째 작은 원소를 찾는다

분할 알고리즘 기반의 재귀적 접근법

select(A, p, r, i) {// 배열 A[p..r]에서 i번째 작은 원소를 찾는다

if (p==r) then return A[p];q = partition(A, p, r);k = q – p + 1;if (i<k) then return select(A, p, q-1, i);else if (i==k) then return A[q];else return select(A, q+1, r, i-k);

}