810 likes | 1.16k Views
5 장 큐. 순서 . 5.1 큐 추상 데이타 타입 5.2 큐의 순차 표현 5.3 C 배열을 이용한 큐의 구현 5.4 큐의 연결 표현 5.5 C 리스트를 이용한 큐의 구현 5.6 큐의 응용 5.7 우선 순위 큐 5.8 덱. 큐 추상 데이타 타입 (1). 큐 (queue) 한쪽 끝 (rear) 에서는 삽입 (enqueue) 만 , 또 다른 끝 (front) 에서는 삭제 (dequeue) 만 하도록 제한되어 있는 유한 순서 리스트 (finite ordered list)
E N D
순서 • 5.1 큐 추상 데이타 타입 • 5.2 큐의 순차 표현 • 5.3 C 배열을 이용한 큐의 구현 • 5.4 큐의 연결 표현 • 5.5 C 리스트를 이용한 큐의 구현 • 5.6 큐의 응용 • 5.7 우선 순위 큐 • 5.8 덱
큐 추상 데이타 타입(1) • 큐(queue) • 한쪽 끝(rear)에서는 삽입(enqueue)만, 또 다른 끝(front)에서는 삭제(dequeue)만 하도록 제한되어 있는 유한 순서 리스트(finite ordered list) • 선입선출, First-In-First-Out(FIFO) 리스트 • 큐에서 제일 먼저 삽입된 원소가 제일 먼저 삭제될 원소가 됨 • 선착순 서버, first-come-first-serve (FCFS) 시스템 • 서비스를 받기 위한 대기 행렬로 볼 수 있음 • 큐의 작동 구조 삭제 삽입 front rear
큐 추상 데이타 타입(2) • 큐에서의 삽입과 삭제 • f : front, r : rear • 큐의 응용 사례 • 운영 체제 : 작업 큐를 통한 제출 순서에 따른 작업 스케줄 • 서비스를 기다리는 작업들의 대기 상태를 나타내는 데 적절 r f r f r f f f r f r r A B A B C A B C D B C D C D A 삽입(A) 삽입(B) 삽입(C) 삽입(D) 삭제 삭제
큐 추상 데이타 타입(3) • 큐 추상 데이타 타입(ADT Queue) ADT Queue 데이타 : 0개 이상의 원소를 가진 유한 순서 리스트 연산 : Q ∈ Queue; item ∈ Element; createQ() ::= create an empty queue; enqueue(Q, item) ::= insert item at the rear of Q; isEmpty(Q) ::= if (Q is empty) then return true else return false; dequeue(Q) ::= if (isEmpty(Q)) then return null else remove and return the front element of Q; remove(Q) ::= if (isEmpty(Q)) then return null else remove the front element of Q; peek(Q) ::= if (isEmpty(Q)) then return null else return the front element of Q; End Queue
큐의 순차 표현(1) • 1차원 배열 • 큐를 표현하는 가장 간단한 방법 • Q[n]을 이용한 순차 표현 • 순차 표현을 위한 변수 • n : 큐에 저장할 수 있는 최대 원소 수 • 두 인덱스 변수 front, rear • 초기화 : front = rear = -1 (공백큐) • 공백큐 : front = rear • 만원 : rear = n-1
큐의 순차 표현(2) • 큐의 연산자(1) createQ() // 공백 큐(Q[])를 생성 Q[n]; front ← -1; // 초기화 rear ← -1; end createQ() isEmpty(Q) // 큐(Q)가 공백인지를 검사 return (front = rear); end isEmpty() // 이 is Empty 연산자는 아주 간단해서 직접 구현하여 사용할 수도 있다. enqueue(Q, item) // 큐(Q)에 원소를 삽입 // Q에 원소 삽입 if (rear=n-1) then queueFull(); // Q가 만원인 상태를 처리 else rear ← rear + 1; Q[rear] ← item; end enqueue()
큐의 순차 표현(3) • 큐의 연산자(2) dequeue(Q) // Q에서 원소를 삭제하여 반환 if (isEmpty(Q)) then return null; // Q가 공백인 상태를 처리 front ← front + 1; return Q[front]; end dequeue() remove(Q) // Q에서 원소를 삭제 if (isEmpty(Q)) then return null; // 큐(Q)가 공백인 상태를 처리 front ← front + 1; end remove() peek(Q) // Q에서 원소를 검색 if (isEmpty(Q)) then return null; // 큐(Q)가 공백인 상태를 처리 else return Q[front+1]; end peek()
큐의 순차 표현(4) • 순차 표현의 문제점 • Rear=n-1인 경우 • 만원이지만, 반드시 n개의 원소가 큐에 있지는 않음 • 큐의 앞에서 삭제로 인해 비 공간이 생길 수 있음 • 빈공간을 없애기 위해 앞쪽으로 이동, front‧rear 재설정 • 시간, 연산의 지연 문제 • 실제로 큐가 만원인 경우 • 배열의 크기를 확장해야 함 • 원형 큐(circular queue) • 순차 표현의 문제점 해결 위해 배열 Q[n]을 원형으로 운영 • 원형 큐의 구현 • 초기화 : front = rear = 0 (공백큐) • 공백큐 : front = rear • 원소 삽입 : rear를 하나 증가시키고, 그 위치에 원소 저장 • 만원 : rear를 하나 증가시켰을 때, rear = front • (실제 front 공간 하나가 비지만, 편의를 위해 그 공간을 희생)
... ... [n-2] [n-2] ... [n-2] a n-3 [n-1] a a a [n-1] [n-1] n-2 1 [2] 1 [2] a a 0 0 [0] [1] [1] [0] [1] [0] front = [0] rear = [n-1] front = [0] rear = [0] (a) 공백 원형 큐 (c) 만원 원형 큐 큐의 순차 표현(5) • 원형 큐의 여러 상태 • 1차원 배열을 원형으로 유지하는 방법 • mod(modulus) 연산자 이용 • 삽입을 위해 먼저 rear를 증가시킬 때 : rear (rear+1) mod n • rear 값은 n-1 다음에 n이 되지 않고, 다시 0으로 되돌아감 • 삭제를 위해 front를 증가시킬 때 : front (front+1) mod n • rear와 마찬가지로, front 값은 n-1 다음에 0이 되어 원형으로 순환 front = [0] rear = [2] (b) 2개의 원소 저장
큐의 순차 표현(6) • 원형 큐에서의 enqueue와 dequeue 연산 enqueue(Q, item) // 원형 큐(Q)에 item을 삽입 rear ← (rear+1) mod n; // 원형 큐(Q) 인덱스 if (front=rear) then queueFull(); // 큐(Q)가 만원인 상태를 처리 Q[rear] ← item; end enqueue() dequeue(Q) // 원형 큐(Q)에서 원소를 삭제하여 반환 if (front=rear) then return null; //큐(Q)가 공백인 상태를 처리 else { front ← (front+1) mod n; // 원형 인덱스 return Q[front]; } end dequeue()
C 배열을 이용한 큐의 구현(1) • Queue를 구현하기 위한 기본 함수 프로토타입 int isEmpty(int *front, int rear); // 큐가 공백인가를 검사 void enqueue(int *rear, element item); // element 타입의 원소를 삽입 element dequeue(int *front, int rear); // element 타입의 원소를 삭제하여 반환 void delete(int *front, int rear); // 원소를 삭제 element peek(int front, int rear); // element 타입의 원소를 검색
C 배열을 이용한 큐의 구현(2) • 1차원 배열(queue[])를 이용한 큐의 구현(1) /* C 배열을 이용한 큐의 구현*/ #define Q_SIZE 100 /* 최대 큐 크기 */ typedef int element; element queue[Q_SIZE]; void enqueue(int *rear, element item) { if(*rear == Q_SIZE-1) { /* 큐가 만원인 경우를 처리 */ printf("Queue is full\n"); return; } queue[++*rear] = item; } int isEmpty (int *front, int rear) { if (*front == rear) return 1; /* 큐가 공백인 경우 */ else return 0; }
C 배열을 이용한 큐의 구현(3) • 1차원 배열(queue[])를 이용한 큐의 구현(2) element dequeue(int *front, int rear) { if (*front == rear) { /* 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else return queue[++*front]; } void delete(int *front, int rear) { if (*front == rear) { /* 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else ++*front; }
C 배열을 이용한 큐의 구현(4) • 1차원 배열(queue[])를 이용한 큐의 구현(3) element peek(int front, int rear) { if (front == rear) { /* 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else { return queue[front+1]; } }
C 배열을 이용한 큐의 구현(5) • 1차원 배열(queue[])를 이용한 큐의 구현(4) • int main( void ) • { • int front = -1; /* 삭제 연산 인덱스 */ • int rear = -1; /* 삽입 연산 인덱스 */ • element data; • enqueue(&rear, 1); • enqueue(&rear, 2); • data = peek(front, rear); • printf("data=%d\n", data); • data = dequeue(&front, rear); • printf("data=%d\n", data); • data = dequeue(&front, rear); • printf("data=%d\n", data); • return 0; • }
rear front data link null 큐의 연결 표현(1) • 연결리스트로 표현된 큐 • 여러 개의 큐를 동시에 필요로 하는 경우에 효율적 • 연결 큐(linked queue)의 구조 • 단순 연결 리스트를 두 개의 포인터 변수 front, rear로 관리 • 초기화 : front = rear = null (공백큐) • 큐의 공백 여부 : front 또는 rear가 null인지 검사를 통해 알 수 있음
큐의 연결 표현(2) • 연결 큐에서의 삽입, 삭제, 검색 연산 구현(1) enqueue(Q, item) // 연결큐(Q)에 item을 삽입 newNode ← getNode(); // 새로운 노드를 생성 newNode.data ← item; newNode.link ← null; if (rear = null) then { // Q가 공백인 경우 rear ← newNode; front ← newNode; } else { rear.link ← newNode; rear ← newNode; } end enqueue() dequeue(Q) // 큐(Q)에서 원소를 삭제하고 값을 반환 if (front = null) then return null; // Q가 공백인 경우 oldNode ← front; item ← front.data; front ← front.link; if (front = null) then rear ← null; // 삭제로 인해 Q가 공백이 되는 이유 retNode(oldNode); return item; end dequeue()
큐의 연결 표현(3) • 연결 큐에서의 삽입, 삭제, 검색 연산 구현(2) delete(Q) // 큐(Q)에서 원소를 삭제 if (front = null) then queueEmpty(); // 큐(Q)가 공백인 경우 else { oldNode ← front; front ← front.link; if (front = null) then rear ← null; retNode(oldNode); } end delete() peek(Q) // 큐(Q)의 front 원소를 검색 if (front = null) then queueEmpty(); // 큐(Q)가 공백인 경우 else return (front.data); end peek()
큐의 연결 표현(4) • 연결큐의 특징 • 삽입, 삭제로 인한 다른 원소들의 이동이 필요 없음 • 연산이 신속하게 수행 • 여러 개의 큐 운영시에도 연산이 간단 • 링크 필드에 할당하는 추가적인 저장 공간 필요 • k개의 큐를 사용 • 큐0, 큐1, 큐2, …, 큐k-1 • 각 큐에 대한 front와 rear : 배열 front[i], rear[i]를 사용 • 초기화 • front[i] null; 0≤i<k • rear[i] null; 0≤i<k
큐의 연결 표현(5) • m개의 큐에서의 삽입, 삭제, 검색 연산 구현(1) enqueue(i, item) // 큐 i에 item을 삽입 newNode ← getNode(); newNode.data ← item; newNode.link ← null; if (front[i] = null) then { // 큐 i가 공백인 경우 front[i] ← newNode; rear[i] ← newNode; } else { // 큐 i가 공백이 아닌 경우 rear[i].link ← newNode; rear[i] ← newNode; } end enqueue()
큐의 연결 표현(6) • m개의 큐에서의 삽입, 삭제, 검색 연산 구현(2) dequeue(i) // 큐 i에서 원소를 삭제하고 값을 반환 if (front[i] = null) then queueEmpty(); // 큐 i가 공백인 경우 else { oldNode ← front[i]; item ← front[i].data; front[i] ← front[i].link; if(front[i] = null) then rear[i] ← null; // 큐 i가 공백이 된 경우 retNode(oldNode); // 노드를 가용 공간 리스트에 반환 return item; } end dequeue()
큐의 연결 표현(7) • m개의 큐에서의 삽입, 삭제, 검색 연산 구현(3) delete(i) // 큐 i에서 원소를 삭제 if (front[i] = null) then queueEmpty(); else { oldNode ← front[i]; front[i] ← front[i].link; if(front[i] = null) then rear[i] ← null; retNode(oldNode); } end delete() peek(i) // 큐 i에서 원소 값을 검색 if (front[i] = null) then queueEmpty(); else return (front[i].data); end peek()
C 리스트를 이용한 큐의 구현(1) • 원소 데이타 · 노드·연결 큐 타입 typedef struct { /* 큐의 struct 원소 타입 */ int id; char name[10]; char grade; } element ; typedef struct queueNode { /* 연결 큐의 노드 타입 */ element data; struct queueNode* link; } queueNode ; typedef struct { /* 연결 큐 데이타 타입 */ queueNode* front; /* 삭제연산 포인터 */ queueNode* rear; /* 삽입연산 포인터 */ int length; /* 큐(리스트)의 원소 수를 표현 */ } linkedQueue ;
front rear length n data link data link data link … null X X X 1 2 n front rear length 1 data link null C 리스트를 이용한 큐의 구현(2) • 큐를 구현한 연결 리스트 표현 n개의 노드(원소)로 구성된 연결 큐 공백 연결 큐 하나의 노드를 가진 연결 큐
C 리스트를 이용한 큐의 구현(3) • 연결 리스트로 큐를 구현한 C 프로그램(1) #include <stdio.h> #include <stdlib.h> typedef struct { /* 연결 큐의 struct 원소 타입 */ int id; char name[10]; char grade; }element ; typedef struct queueNode { /* 연결 큐의 노드 타입 */ element data; struct queueNode* link; } queueNode ; typedef struct { /* 연결 큐 데이타 타입 */ queueNode* front; /* 삭제연산 포인터 */ queueNode* rear; /* 삽입연산 포인터 */ int length; /* 큐(리스트)의 원소 수를 표현 */ }linkedQueue ;
C 리스트를 이용한 큐의 구현(4) • 연결 리스트로 큐를 구현한 C 프로그램(2) linkedQueue* createQ() { /* 연결 큐(q)를 생성하고 초기화 */ linkedQueue* q q = (linkedQueue*)malloc(sizeof(linkedQueue)); q->front = NULL; q->rear = NULL; q->length = 0; return q; } int isEmpty (linkedQueue* q) { /* 연결 큐가 공백인가를 검사 */ return (q->length == 0); }
C 리스트를 이용한 큐의 구현(5) • 연결 리스트로 큐를 구현한 C 프로그램(3) void enqueue(linkedQueue* q, element item) { /* 연결 큐에 원소를 삽입 */ queueNode* newNode; newNode = (queueNode*)malloc(sizeof(queueNode)); newNode->data = item; newNode->link = NULL; if (q->length==0) { /* 연결 큐가 공백인 경우 */ q->front = q->rear = newNode; } else { q->rear->link = newNode; q->rear = newNode; } q->length++; }
C 리스트를 이용한 큐의 구현(6) • 연결 리스트로 큐를 구현한 C 프로그램(4) element dequeue(linkedQueue* q) { /* 연결 큐에서 원소를 삭제하고 반환 */ queueNode* temp; element item; if (q->length==0) { /* 연결 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else { item = q->front->data; temp = q->front; q->front = q->front->link; if (q->front == NULL) q->rear = NULL; q->length--; free(temp); /* 삭제된 노드를 반환 */ return item; } }
C 리스트를 이용한 큐의 구현(7) • 연결 리스트로 큐를 구현한 C 프로그램(5) void delete(linkedQueue* q) { /* 연결 큐에서 원소를 삭제 */ queueNode* temp; if (q->length==0) { /* 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else { temp = q->front; q->front = q->front->link; if (q->front == NULL) q->rear = NULL; q->length--; free(temp); /* 삭제된 노드를 반환 */ } }
C 리스트를 이용한 큐의 구현(8) • 연결 리스트로 큐를 구현한 C 프로그램(6) element peek(linkedQueue* q) { /* 연결 큐에서 원소를 검색 */ if (q->length == 0) { /* 큐가 공백인 경우 */ printf("Queue is empty\n"); exit(1); } else return q->front->data; } int main() { element item; linkedQueue* q; q = createQ(); item.id = 123; strcpy(item.name, "Hong"); item.grade ='A'; enqueue(q, item); · · · }
큐의 응용 - 운영체제에서 큐 • 운영체제에서 큐의 응용 • 상이한 속도로 실행하는 두 프로세스 간의 상호 작용을 조화시키는 버퍼 역할을 담당 • 예: CPU와 프린터 사이의 프린트 버퍼(printBufferQueue) • 프린트 버퍼에서의 판독과 기록 작업 writeLine() // CPU가 프린트 해야 할 라인을 프린트 버퍼 큐에 삽입 if (there is a line L to print) and (printBufferQueue ≠ full) and (printBufferQueue ≠ busy) then enqueue(printBufferQueue, L); end writeLine() readLine() // 프린터가 프린트 버퍼 큐의 라인들을 프린트 if(printBufferQueue ≠ empty) and (printBufferQueue ≠ busy) then { L ← dequeue(printBufferQueue); print L; } end readLine()
컴퓨터 시뮬레이션(1) • 시뮬레이션의 정의 • 어떤 물리적 시스템의 행태를 분석하고 예측하기 위해 컴퓨터 모델을 통해 시뮬레이트하는 것 • 물리적 시스템 • 특정 목적을 달성하기 위해 동작하고 상호 작용하는 독립적인 원소나 개체의 집합
컴퓨터 시뮬레이션(2) • 물리적 시스템의 상태 • 일련의 상태 변수(state variable)를 사용하여 표현 • 공항의 항공기 교통 시뮬레이션 예 • 개체: 항공기 • 상태: 항공기의 상태 (공중, 지상에서 착륙이나 이륙) • 보통 시간대별로 측정 • 연속적 시스템(continuous system) 시뮬레이션 • 시스템 상태는 시간에 따라 연속적으로 변함 • 이산 시스템(discrete system) 시뮬레이션 • 상태 변수들은 어떤 특정 사건 발생 시점에서만 변함
컴퓨터 시뮬레이션(3) • 시뮬레이션에서의 시간 • 물리적 시스템에서의 시간을 의미하는 시뮬레이트 되는 시간 (simulated time)과 시뮬레이션 프로그램에서의 연산 시간 (computation time)을 분명하게 구별 해야함 • 대부분의 경우 시뮬레이트 되는 시간보다 연산 시간이 훨씬 짧음 • 예 : 기상 예측 시스템
컴퓨터 시뮬레이션(4) • 큐잉 시스템(queueing system) • 큐잉 시스템의 특징 • 대부분의 물리적 시스템을 모델링 • 서비스를 기다리는 대기선(waiting line)을 가진 시스템 • 대기선 : 큐의 선입선출(FIFO) 성질을 만족 • 큐잉 시스템의 종류 • 단일 서버 큐잉 시스템 • 다중 큐 다중 서버 큐잉 시스템 • 큐잉 네트워크
도착 완료 큐 서버 컴퓨터 시뮬레이션(5) • 단일 서버 큐잉 시스템 • 단일 큐, 단일 서버로 구성 • 시뮬레이트 • 가정 • 고객 도착 시간 간격의 분포 : 고객들의 도착시간은 어떤 확률 분포 함수 A(t)에 따라 상이하다고 가정 • 서비스 시간 분포 : 개개 고객의 서비스 시간은 어떤 확률 분포 함수 S(t)에 따라 상이하게 제공된다고 가정 • 위의 정보를 기초로 큐의 평균 길이, 고객의 평균 대기 시간, 서버의 작업 처리 능력 등을 분석 • 단일 서버 큐잉 시스템
컴퓨터 시뮬레이션(6) • 큐잉 시스템 시뮬레이션 • 구성 요소 • 고객 큐 : 대기선을 모델링 • 서버 : 고객들을 서비스 • 스케줄러 : 시뮬레이션하는 동안 사건이 일어날 시간을 스케줄 • 시뮬레이션에 필요한 자료 • 새로운 고객 도착 : 확률 분포 함수 A(t)에 따라 정해지는 시간 • 서비스 받고 시스템 나감 : 확률 분포 함수 S(t)에 따라 결정되는 시간 • 시뮬레이션의 종류 • 시간 중심 시뮬레이션(time-driven simulation) • 시뮬레이션 클록에 일정 단위 시간을 계속적으로 증가시키면서 시뮬레이션을 수행 • 사건 중심 시뮬레이션(event-driven simulation) • 시뮬레이션 클록을 사건이 발생할 때마다 경과된 시간을 증가시키고, 상태 변수를 갱신하면서 시뮬레이션을 수행
컴퓨터 시뮬레이션(7) • 단일 서버 큐잉 시스템 시뮬레이션(1) timeDrivenSimulation(startSimulation, endSimulation) // startSimulation: 시뮬레이션 시작 시간 // endSimulation: 시뮬레이션 종료 시간 // 필요한 여러 상태 변수들을 초기화 clock ← startSimulation; // 시뮬레이션 시계(clock) arrivalTime; // 고객이 서비스를 받기 위해 시스템에 도착한 시간 leaveTime; // 고객이 서비스를 받고 떠나는 시간 serverState; // 서버의 busy(서비스 중) 또는 idle(휴식 중) 상태를 표현 tick; // 시뮬레이션 시계의 단위 시간 queue; // 고객이 서비스를 받기 위해 대기하는 큐
컴퓨터 시뮬레이션(8) • 단일 서버 큐잉 시스템 시뮬레이션(2) while (clock < endSimulation) do { // 시뮬레이션 종료 시간이 되지 않은 경우 clock ← clock + tick; // 클록의 단위 시간을 증가 if (clock ≥ arrivalTime) then { // 새로운 고객이 도착한 경우 enqueue(queue, customer); // 고객(customer), arrivalTime은 큐로 들어가 서비스를 대기 update(statistics); // 통계 분석 데이타(statistics) 처리 arrivalTime ← clock + arrival(clock); // 다음 고객 도착 시간을 생성 // arrival(): 고객의 도착 시간 간격 } if (clock ≥ leaveTime) then // 고객의 서비스가 완료된 경우 serverState ← idle; // 서버는 쉬는 상태로
컴퓨터 시뮬레이션(9) • 단일 서버 큐잉 시스템 시뮬레이션(3) if (serverState = idle and not isEmpty(queue)) then { // 다음 고객을 서비스할 수 있는가를 점검 dequeue(queue); // 다음 차례의 고객에 서비스 시작 update(statistics); // 통계 분석 데이타(statistics) 처리 serverState ← busy; // 서버를 서비스 중인 상태로 leaveTime ← clock + service(clock); // 고객이 서비스를 받고 떠나는 시간을 설정 // service(t): 고객의 서비스 시간 생성 } } // end while end timeDrivenSimulation()
Q1 S1 도착 완료 Q3 S3 Q2 S2 컴퓨터 시뮬레이션(10) • 복잡한 큐잉 시스템 • 다중 큐 다중 서버 큐잉 시스템 • 큐잉 네트워크 Q1 S1 Q2 S2 도착 완료 ... ... Qk Sm
우선 순위 큐(1) • 우선 순위 큐(priority queue) • 원소에 부여된 우선 순위에 따라 우선 순위가 가장 높은 원소부터 삭제하는 자료 구조 • 스택과 큐도 우선 순위 큐의 일종 • 스택 : 삽입 시간이 가장 짧은 원소에 가장 높은 우선 순위를 부여한 우선 순위 큐 • 큐 : 삽입 시간이 가장 오래된 원소에 가장 높은 우선 순위를 부여한 우선 순위 큐 • 원소의 우선 순위 표현과 연산 • 보통 우선 순위 key 값을 사용 • 삭제시 : 우선 순위가 가장 높은 원소가 제일 먼저 삭제 • 삽입 : 우선 순위와 관계없이 임의의 순서로 언제나 수행
우선 순위 큐(2) • 우선 순위 큐(priority queue) 추상 데이타 타입 ADT PriorityQueue 데이타 : 우선순위를 가진 0개 이상의 원소로 된 수집(collection) 연산 : pQ ∈ PriorityQueue; item ∈ Element; createQ() ::= create an empty priority queue; length(pQ) ::= return the number of items in pQ; insert(pQ, item) ::= insert the item into pQ; delete(pQ) ::= if (isEmpty(pQ)) then return error else {delete the item with the highest priority from pQ}; End PriorityQueue
우선 순위 큐(3) • 원소들의 비교 연산 • 우선 순위 큐의 전체 순서(total order) 관계 성립 • 1) 반사적(reflexive) 성질 : ki ≤ ki • 2) 반대칭(antisymmetric) 성질 : k1 ≤ k2이고 k2 ≤ k1이면, k1 = k2 • 3) 이행적 성질(transitive) : k1 ≤ k2이고 k2 ≤ k3이면, k1 ≤ k3 • 우선 순위 큐의 모든 원소 : 우선 순위에 따라 일렬로 정렬
C에서의 우선순위 큐(1) • PriorityQueue 구현을 위한 기본 함수 프로토타입 priorityQ* createQ(void); /* 공백 우선순위 큐의 생성 */ void insert(priorityQ* pQ, element item); /* 우선순위 큐 pQ에 원소 item을 삽입 */ element delete(priorityQ* pQ); /* 큐 pQ에서 우선순위가 제일 높은 원소를 삭제하여 반환 */
C에서의 우선순위 큐(2) • 우선순위 큐 정렬 함수 • 우선 순위 큐 정렬(priority queue sorting)을 구현 void priorityQsort(int *a, int length) { int i; priorityQ* pQ; pQ = createQ(); /* 공백 우선순위 큐를 생성 */ for (i = 0; i < length; i++) { insert(pQ, a[i]); /*배열 a[]의 모든 원소를 우선순위 큐 pQ에 삽입 */ } for (i = length-1; i >=0; i--) { a[i] = delete(pQ); /*우선순위 큐 pQ에 있는 원소를 모두 배열 a[]로 다시 이동 */ } }
C에서의 우선순위 큐(3) • 우선순위 큐 정렬 C 프로그램(1) • 정수 값을 우선 순위 큐 정렬 방법으로 정렬 void main() { int i; int n = 10; /*정렬할 원소 수 */ element data[]; data = (element*)malloc(n*sizeof(element)); for (i = 0; i < n; i++) { data[i].key = (3*i-13)*(3*i-13); /*정수 키 값을 가진 10개의 원소를 생성하여 저장 */ printf("%d, ", data[i].key); /*배열 data[]에 저장된 원소의 키 값을 프린트 */ /* : 169, 100, 49, 16, 1, 4, 25, 64, 121, 196 */ } printf("\r\n"); priorityQsort(data, n); /*배열 data[]를 priorityQsort()로 정렬 */ for (i = 0; i < n; i++) { printf("%d, ", data[i].key); /*정렬된 배열 data[]의 각 원소의 키 값을 프린트 */ /* : 196, 169, 121, 100, 64, 49, 25, 16, 4, 1 */ } printf("\r\n"); free(data); }
C에서의 우선순위 큐(4) • 우선순위 큐 정렬 C 프로그램(2) void priorityQsort(element* a, int size) { int i; priorityQ* pQ; pQ = createQ(); /* 공백 우선순위 큐를 생성 */ for (i = 0; i < size; i++) { insert(pQ, a[i]); /*배열 a[]의 모든 원소를 우선순위 큐 pQ에 삽입 */ } for (i = size-1; i >=0; i--) { a[i] = delete(pQ); /*우선순위 큐 pQ에 있는 원소를 모두 배열 a[]로 다시 이동 */ } free(pQ); }
C 우선순위 큐의 구현(1) • 정렬된 연결 리스트를 이용한 구현(1) • 정렬된 연결 리스트 • 원소의 우선 순위에 따라 내림차순으로 유지 • 삭제 : 단순히 리스트의 첫 번째 노드를 삭제 • 삽입 : 원소의 우선 순위에 알맞은 위치에 저장 • 삭제 연산의 비용은 적고, 삽입 연산의 비용은 큼 • struct element, struct pListNode • Struct pListNode : 연결 리스트의 노드 구조의 정의 typedef struct { /* 큐의 struct 원소 타입 */ int key; /* 우선순위 값을 표현 */ char name[10]; char grade; }element ; typedef struct pListNode { element data; struct pListNode* link; } pListNode;