티스토리 뷰
Programming/뇌를 자극하는 알고리즘
뇌를 자극하는 알고리즘 - 7. 우선순위 큐와 힙: 우선순위 큐(Priority Queue)
ProjectKMS 2010. 10. 25. 16:01구현 소스
PriorityQueue.h
#ifndef PRIORITYQUEUE_H #define PRIORITYQUEUE_H #include <stdio.h> #include <memory.h> #include <stdlib.h> typedef struct tagPQNode { int Priority; // 우선순위 void* Data; // 다양한 자료형을 우선순위큐 안에 담을 수 있도록 void* type으로 선언함. } PQNode; typedef struct tagPriorityQueue { PQNode* Nodes; // Node를 담는 배열 int Capacity; int UsedSize; } PriorityQueue; //////////// 함수 정의 /////////////// PriorityQueue* PQ_Create(int Init); void PQ_Destroy(PriorityQueue* PQ); void PQ_Enqueue(PriorityQueue* PQ, PQNode NewNode); void PQ_Dequeue(PriorityQueue* PQ, PQNode* Root); int PQ_GetParent(int Index); int PQ_GetLeftChild(int Index); void PQ_SwapNodes(PriorityQueue* PQ, int Index1, int Index2); int PQ_IsEmpty(PriorityQueue* PQ); #endif
----------------------------------------------------------------------------------------
PriorityQueue.cpp
#include "PriorityQueue.h" // Priority Queue 생성 PriorityQueue* PQ_Create(int Init) { PriorityQueue* NewPQ = (PriorityQueue*) malloc( sizeof(PriorityQueue) ); NewPQ->Capacity = Init; NewPQ->Nodes = (PQNode*) malloc( sizeof(PQNode) * NewPQ->Capacity ); NewPQ->UsedSize = 0; return NewPQ; } // Priority Queue 파괴 void PQ_Destroy(PriorityQueue* PQ) { free(PQ->Nodes); free(PQ); } // Node를 삽입하는 함수 // 1. Capacity와 UsedSize를 검사후 용량을 늘리는 작업 // 2. Heap 자료구조의 규칙 유지. - Root노드는 최소값, 부모노드는 L,R Child보다 값이 작음. // - 새로 삽입할 노드를 배열의 젤 뒤(Leaf노드들중 최 우측)에 삽입후 부모와 값 비교 void PQ_Enqueue(PriorityQueue* PQ, PQNode NewNode) { int CP = PQ->UsedSize ; // Current Position int PP = PQ_GetParent(CP); // Parent Position if( PQ->UsedSize == PQ->Capacity) { // 용량이 가득 찼다면 if(PQ->Capacity == 0) PQ->Capacity = 1; PQ->Capacity *= 2; // 자기 자신의 두배 만큼 증가 PQ->Nodes = (PQNode*) realloc( PQ->Nodes , sizeof(PQNode) * PQ->Capacity ); } // 용량 재조정 작업후 Heap 자료구조 규칙 유지 PQ->Nodes[CP] = NewNode; while( CP > 0 && ( PQ->Nodes[CP].Priority < PQ->Nodes[PP].Priority ) ) { // CP의 우선순위가 PP의 우선순위 보다 낮은 경우 - CP와 PP를 교환 PQ_SwapNodes(PQ, CP, PP); CP = PP; PP = PQ_GetParent(CP); } (PQ->UsedSize) ++; } // Heap의 최소값 삭제에 해당하는 함수 // 1. 최소값(Heap의 Root)를 매개변수 Root에 Copy 한 후 // - Heap 자료구조 규칙 유지 작업 - Root노드는 최소값, 부모노드는 L,R Child보다 값이 작음. // - 배열 젤 뒤(Leaf노드들중 최 우측)의 노드를 Root Node자리에 넣은후 (0번) L,R Child들 중 작은 값과 비교후 // 작다면 자료 교환. (이 때의 값이라는건 우선순위를 말함) // 2. 삭제 작업이 완료 된 후 UsedSize가 Capacity의 값보다 심하게 작을때(ex) UsedSize < Capacity/2 ) // 용량을 줄이는 작업. void PQ_Dequeue(PriorityQueue* PQ, PQNode* Root) { int PP = 0; // Parent Position int LCP = 0; // Left Child Position int RCP = 0; // Right Child Position memcpy(Root, & PQ->Nodes[PP], sizeof(PQNode) ); memset(& PQ->Nodes[PP], 0, sizeof(PQNode) ); // 삭제되는 Root Node를 초기화 PQ->UsedSize--; // 최소값 삭제로 Node수 감소 PQ_SwapNodes(PQ, PP, PQ->UsedSize); // Left노드들중 최 우측을 Root의 위치로 이동후 // Heap 자료구조 규칙 검사 후 재 구성 LCP = PQ_GetLeftChild(PP); RCP = LCP + 1; while(1) { int SC = 0 ; // Selected Child // LC와 RC중 작은 값을 선택후 P와 값을 비교하고 작다면 P와 교환함. if(LCP >= PQ->UsedSize) break; // LCP가 PQ_GetLeftChild 함수에 인해 UsedSize보다 큰 값을 가지면 메모리 참조 오류를 //발생시키므로 예외처리 if(RCP >= PQ->UsedSize) { // RCP가 UsedSize보다 크다면 LCP(RCP-1)의 부모노드는 LC만 가지고 있다는 뜻이므로 SC = LCP; } else // 그 외의 경우 LC와 RC를 비교후 작은 값에 해당하는 index를 SC로 { if( PQ->Nodes[LCP].Priority < PQ->Nodes[RCP].Priority) SC = LCP; else SC = RCP; } // 선택된 SC와 PP의 우선순위를 비교 후 PP의 우선순위가 크다면 SC와 교환 if( PQ->Nodes[SC].Priority < PQ->Nodes[PP].Priority ) { PQ_SwapNodes(PQ, PP, SC); PP = SC; // 아래로 타고 내려감. } else break; LCP = PQ_GetLeftChild(PP); RCP = LCP + 1; } // 용량 재조정 if( PQ->UsedSize < (PQ->Capacity / 2) ) { PQ->Capacity /= 2; PQ->Nodes = (PQNode*) realloc(PQ->Nodes , sizeof(PQNode) * PQ->Capacity ); } } // Array로 표현된 Heap 자료구조의 특정노드의 부모를 얻으려면.. (Index-1)/2; int PQ_GetParent(int Index) { return (Index-1)/2; } // Array로 표현된 Heap 자료구조의 특정노드의 LeftChild를 얻으려면 (Index*2)+1; int PQ_GetLeftChild(int Index) { return (Index*2)+1; } void PQ_SwapNodes(PriorityQueue* PQ, int Index1, int Index2) { int CS = sizeof(PQNode); // Copy Size PQNode* Temp = (PQNode*) malloc( CS ); // swap 구현 memcpy(Temp, &(PQ->Nodes[Index1]), CS); memcpy(&( PQ->Nodes[Index1] ), &( PQ->Nodes[Index2] ), CS); memcpy(&( PQ->Nodes[Index2] ), Temp, CS); free(Temp); } // Heap이 비어있는지 여부를 반환 int PQ_IsEmpty(PriorityQueue* PQ) { return ( PQ->UsedSize == 0 ); }
----------------------------------------------------------------------------------------
main.cpp
#include "PriorityQueue.h" int main() { PriorityQueue* PQ = PQ_Create(2); PQNode MinNode; int i; PQNode Node[7] = { {54, (void*) "이성과 데이트"}, {157,(void*) "야동감상"}, {100, (void*) "게임하기"}, {10, (void*) "공부"}, {32, (void*) "밥먹기"}, {20, (void*) "돈벌기"}, {50,(void*) "친구와 술먹기"} }; for(i=0; i<7; i++) PQ_Enqueue(PQ, Node[i]); // Priority Queue // {10, 32, 20, 157, 54, 100, 50} printf(" Priorty Queue에 존재하는 작업의 수 : %d\n", PQ->UsedSize); while( !PQ_IsEmpty(PQ) ) { PQ_Dequeue(PQ, &MinNode); printf(" Work : %s (Priority : %d)\n", MinNode.Data , MinNode.Priority); } PQ_Destroy(PQ); return 0; }
----------------------------------------------------------------------------------------
실행 결과
'Programming > 뇌를 자극하는 알고리즘' 카테고리의 다른 글
뇌를 자극하는 알고리즘 - 8. 해시 테이블 : 체이닝(Chaining) (0) | 2010.11.07 |
---|---|
뇌를 자극하는 알고리즘 - 8. 해시 테이블 : 나눗셈법으로 구현된 간단한 해시 테이블 (0) | 2010.11.07 |
뇌를 자극하는 알고리즘 - 7. 우선순위 큐와 힙: 힙(Heap) (0) | 2010.10.23 |
뇌를 자극하는 알고리즘 - 6. 탐색 : 이진 탐색 트리(Binary Search Tree) (0) | 2010.10.22 |
뇌를 자극하는 알고리즘 - 6. 탐색 : 이진 탐색(Binary Search) (0) | 2010.10.21 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Ice Climber
- Tales of the Float Land
- 뇌를 자극하는 알고리즘
- Data Structures in C
- 그림 맞추기 게임
- Linked list
- graph
- Kinect Game Project
- PtInRect
- WinAPI
- Pixel 색상값으로 구현한 간단한 충돌
- Farseer Physics
- Queue
- Stack
- Game project
- 열혈강의C
- Kinect Programming
- IntersectRect
- Digits Folding
- WM_TIMER
- Win32 API
- MFC 예제
- quick sort
- 2D Game Project
- 윈도우즈 API 정복
- WM_CONTEXTMENU
- Tree
- PackMan
- Hash table
- SetTimer
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함