[자료구조 과제] 큐 대기줄 시뮬레이션
1. 실행 결과
[현재 시각 알림]
현재시각 : 1분
[고객 알림]
고객 번호 : 0번 고객님
들어온 시간 : 1분
서비스 시간 : 3분
고객0 : 1번 서버에 줄이 0명으로 제일 적네. 저기로 가야겠다.
==================================
[고객 알림]
고객 번호 : 1번 고객님
들어온 시간 : 1분
서비스 시간 : 5분
고객1 : 2번 서버에 줄이 0명으로 제일 적네. 저기로 가야겠다.
==================================
[1번 서버 현황]
[1번 서버님 서비스 시작]
고객 번호 : 0번 고객님
서비스 시작 시간 : 1분
대기시간 : 0분
==================================
[2번 서버 현황]
[2번 서버님 서비스 시작]
고객 번호 : 1번 고객님
서비스 시작 시간 : 1분
대기시간 : 0분
==================================
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
고객이 오기를 대기 중입니다!
[5번 서버 현황]
고객이 오기를 대기 중입니다!
[현재 시각 알림]
현재시각 : 2분
[고객 알림]
고객 번호 : 2번 고객님
들어온 시간 : 2분
서비스 시간 : 3분
고객2 : 3번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 0번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
아직 1번 고객님의 서비스가 끝나지 않았습니다!
[3번 서버 현황]
[3번 서버님 서비스 시작]
고객 번호 : 2번 고객님
서비스 시작 시간 : 2분
대기시간 : 0분
==================================
[4번 서버 현황]
고객이 오기를 대기 중입니다!
[5번 서버 현황]
고객이 오기를 대기 중입니다!
[현재 시각 알림]
현재시각 : 3분
[고객 알림]
고객 번호 : 3번 고객님
들어온 시간 : 3분
서비스 시간 : 5분
고객3 : 4번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 0번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
아직 1번 고객님의 서비스가 끝나지 않았습니다!
[3번 서버 현황]
아직 2번 고객님의 서비스가 끝나지 않았습니다!
[4번 서버 현황]
[4번 서버님 서비스 시작]
고객 번호 : 3번 고객님
서비스 시작 시간 : 3분
대기시간 : 0분
==================================
[5번 서버 현황]
고객이 오기를 대기 중입니다!
[현재 시각 알림]
현재시각 : 4분
[고객 알림]
고객 번호 : 4번 고객님
들어온 시간 : 4분
서비스 시간 : 5분
고객4 : 5번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
고객이 오기를 대기 중입니다!
[2번 서버 현황]
아직 1번 고객님의 서비스가 끝나지 않았습니다!
[3번 서버 현황]
아직 2번 고객님의 서비스가 끝나지 않았습니다!
[4번 서버 현황]
아직 3번 고객님의 서비스가 끝나지 않았습니다!
[5번 서버 현황]
[5번 서버님 서비스 시작]
고객 번호 : 4번 고객님
서비스 시작 시간 : 4분
대기시간 : 0분
==================================
[현재 시각 알림]
현재시각 : 5분
[고객 알림]
고객 번호 : 5번 고객님
들어온 시간 : 5분
서비스 시간 : 2분
고객5 : 1번 서버에 줄도 없고 서비스 하지 않네.
==================================
[고객 알림]
고객 번호 : 6번 고객님
들어온 시간 : 5분
서비스 시간 : 1분
고객6 : 2번 서버에 줄이 0명으로 제일 적네. 저기로 가야겠다.
==================================
[1번 서버 현황]
[1번 서버님 서비스 시작]
고객 번호 : 5번 고객님
서비스 시작 시간 : 5분
대기시간 : 0분
==================================
[2번 서버 현황]
아직 1번 고객님의 서비스가 끝나지 않았습니다!
[3번 서버 현황]
3 서버 : 옆 손님 이쪽으로 와주세요~
[3번 서버님 서비스 시작]
고객 번호 : 6번 고객님
서비스 시작 시간 : 5분
대기시간 : 0분
==================================
고객이 오기를 대기 중입니다!
[4번 서버 현황]
아직 3번 고객님의 서비스가 끝나지 않았습니다!
[5번 서버 현황]
아직 4번 고객님의 서비스가 끝나지 않았습니다!
[현재 시각 알림]
현재시각 : 6분
[고객 알림]
고객 번호 : 7번 고객님
들어온 시간 : 6분
서비스 시간 : 1분
고객7 : 3번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 5번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
2 서버 : 옆 손님 이쪽으로 와주세요~
[2번 서버님 서비스 시작]
고객 번호 : 7번 고객님
서비스 시작 시간 : 6분
대기시간 : 0분
==================================
고객이 오기를 대기 중입니다!
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
아직 3번 고객님의 서비스가 끝나지 않았습니다!
[5번 서버 현황]
아직 4번 고객님의 서비스가 끝나지 않았습니다!
[현재 시각 알림]
현재시각 : 7분
[고객 알림]
고객 번호 : 8번 고객님
들어온 시간 : 7분
서비스 시간 : 5분
고객8 : 2번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
1 서버 : 옆 손님 이쪽으로 와주세요~
[1번 서버님 서비스 시작]
고객 번호 : 8번 고객님
서비스 시작 시간 : 7분
대기시간 : 0분
==================================
[2번 서버 현황]
고객이 오기를 대기 중입니다!
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
아직 3번 고객님의 서비스가 끝나지 않았습니다!
[5번 서버 현황]
아직 4번 고객님의 서비스가 끝나지 않았습니다!
[현재 시각 알림]
현재시각 : 8분
[고객 알림]
고객 번호 : 9번 고객님
들어온 시간 : 8분
서비스 시간 : 1분
고객9 : 2번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 8번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
[2번 서버님 서비스 시작]
고객 번호 : 9번 고객님
서비스 시작 시간 : 8분
대기시간 : 0분
==================================
고객이 오기를 대기 중입니다!
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
고객이 오기를 대기 중입니다!
[5번 서버 현황]
아직 4번 고객님의 서비스가 끝나지 않았습니다!
[현재 시각 알림]
현재시각 : 9분
[고객 알림]
고객 번호 : 10번 고객님
들어온 시간 : 9분
서비스 시간 : 1분
고객10 : 2번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 8번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
[2번 서버님 서비스 시작]
고객 번호 : 10번 고객님
서비스 시작 시간 : 9분
대기시간 : 0분
==================================
고객이 오기를 대기 중입니다!
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
고객이 오기를 대기 중입니다!
[5번 서버 현황]
고객이 오기를 대기 중입니다!
[현재 시각 알림]
현재시각 : 10분
[고객 알림]
고객 번호 : 11번 고객님
들어온 시간 : 10분
서비스 시간 : 3분
고객11 : 2번 서버에 줄도 없고 서비스 하지 않네.
==================================
[1번 서버 현황]
아직 8번 고객님의 서비스가 끝나지 않았습니다!
[2번 서버 현황]
[2번 서버님 서비스 시작]
고객 번호 : 11번 고객님
서비스 시작 시간 : 10분
대기시간 : 0분
==================================
[3번 서버 현황]
고객이 오기를 대기 중입니다!
[4번 서버 현황]
고객이 오기를 대기 중입니다!
[5번 서버 현황]
고객이 오기를 대기 중입니다!
[마감시간까지의 통계 출력]
서비스를 받은 고객수 : 12명
전체 대기 시간 : 0분
1인당 평군 대기 시간 : 0.000000분
아직 대기중인 고객수 : 0
-> [1번 서버님]
총 일한 시간 : 6분
총 대기 시간 : 1분
마감시간이므로 고객 8님의 남은 업무 1분은 다음 날로 넘기겠습니다!
-> [2번 서버님]
총 일한 시간 : 4분
총 대기 시간 : 4분
마감시간이므로 고객 11님의 남은 업무 2분은 다음 날로 넘기겠습니다!
-> [3번 서버님]
총 일한 시간 : 2분
총 대기 시간 : 7분
-> [4번 서버님]
총 일한 시간 : 4분
총 대기 시간 : 5분
-> [5번 서버님]
총 일한 시간 : 4분
총 대기 시간 : 5분
소스
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define MAX_SERVER_SIZE 5 #define MAX_QUEUE_SIZE 100 FILE* fp; typedef struct { int id; int arrival_time; int service_time; } element; typedef struct { element queue[MAX_QUEUE_SIZE]; int front, rear; } QueueType; typedef struct { int id; int waited_time; int service_total_time; int service_time; element customerIDserving; // 현재 서비스 받고 있는 고객 QueueType waitingQueue; } ServerElement; typedef struct { ServerElement queue[MAX_QUEUE_SIZE]; int front, rear; } ServerQueue; ServerQueue serverQueue; int serverCnt = 0; void error(const char *msg) { printf("[Error] %s\n\n", msg); fprintf(fp, "[Error] %s\n\n", msg); } // 큐 삽입함수 // q : 큐 배열을 관리하는 구조체 포인터 변수 // item : 집어넣을 element, 고객의 정보가 담긴 변수 void enqueue(QueueType *q, element item) { if (isOver(q)) error("큐가 포화상태입니다"); q->rear = (q->rear + 1) % MAX_QUEUE_SIZE; q->queue[q->rear] = item; } void enqueueServer(ServerQueue *q, ServerElement item) { if (isOver(q)) error("서버큐가 포화상태입니다"); q->rear = (q->rear + 1) % MAX_QUEUE_SIZE; q->queue[q->rear] = item; } // 삭제 함수 element dequeue(QueueType *q) { if (isEmpty(q)) error("큐가 공백상태입니다"); q->front = (q->front + 1) % MAX_QUEUE_SIZE; return q->queue[q->front]; } ServerElement dequeueServer(ServerQueue *q) { if (isEmpty(q)) error("서버큐가 공백상태입니다"); q->front = (q->front + 1) % MAX_QUEUE_SIZE; return q->queue[q->front]; } // 큐가 비어있는지 확인해주는 함수 int isEmpty(QueueType *q) { return (q->front == q->rear); } int isEmptyServer(ServerQueue *q) { return (q->front == q->rear); } // 큐가 꽉 찼는지 확인해주는 함수 int isOver(QueueType *q) { return ((q->rear + 1) % MAX_QUEUE_SIZE == q->front); } int isOverServer(ServerQueue *q) { return ((q->rear + 1) % MAX_QUEUE_SIZE == q->front); } // 0~1 사이 난수 제네레이터 함수 double getRandom() { return rand() / (double)RAND_MAX; } // 시뮬레이션 변수들 int duration = 10; // 시뮬레이션 시간 double arrival_prob = 0.7; // 하나의 시간 단위에 도착하는 평균 고객의 수 int max_serv_time = 5; // 하나의 고객에 대한 최대 서비스 시간 int clock = 0; // 프로그램 상에서 흐르는 현재 시간 // 시뮬레이션 결과 변수들 int customers = 0; // 전체고객수 int served_customers = 0; // 서비스받은 고객수 int waited_time = 0; // 고객들이 기다린 시간 // 랜덤 숫자로 고객이 도착했는지 도착하지 않았는지를 알려주는 함수 int is_customer_arrived() { if (getRandom() < arrival_prob) return TRUE; else return FALSE; } // 새로운 Customer을 대기줄 큐에 삽입하는 함수 void insert_customer(int arrival_time, QueueType* queue) { element customer; customer.id = customers++; customer.arrival_time = arrival_time; customer.service_time = (int)(max_serv_time * getRandom()) + 1; enqueue(queue, customer); printf("고객 번호 : %d번 고객님\n", customer.id); printf("들어온 시간 : %d분\n", customer.arrival_time); printf("서비스 시간 : %d분\n", customer.service_time); fprintf(fp, "고객 번호 : %d번 고객님\n", customer.id); fprintf(fp, "들어온 시간 : %d분\n", customer.arrival_time); fprintf(fp, "서비스 시간 : %d분\n", customer.service_time); } // 큐에서 기다리는 고객을 꺼내어 고객의 서비스 시간을 반환한다. int remove_customer(ServerElement* serverElement) { int service_time = 0; element customer; if (isEmpty(&serverElement->waitingQueue)) return 0; customer = dequeue(&serverElement->waitingQueue); service_time = customer.service_time - 1; served_customers++; waited_time += clock - customer.arrival_time; printf("[%d번 서버님 서비스 시작]\n", serverElement->id); printf("고객 번호 : %d번 고객님\n", customer.id); printf("서비스 시작 시간 : %d분\n", clock); printf("대기시간 : %d분\n", clock - customer.arrival_time); fprintf(fp, "[%d번 서버님 서비스 시작]\n", serverElement->id); fprintf(fp, "고객 번호 : %d번 고객님\n", customer.id); fprintf(fp, "서비스 시작 시간 : %d분\n", clock); fprintf(fp, "대기시간 : %d분\n", clock - customer.arrival_time); fprintf(fp, "==================================\n"); serverElement->customerIDserving.id = customer.id; serverElement->customerIDserving.arrival_time = clock; serverElement->customerIDserving.service_time = customer.service_time; return service_time; } // 통계치를 출력한다. void print_stat() { int i; printf("\n[마감시간까지의 통계 출력]\n"); printf("서비스를 받은 고객수 : %d명\n", served_customers); printf("전체 대기 시간 : %d분\n", waited_time); printf("1인당 평군 대기 시간 : %f분\n", (double)waited_time / served_customers); printf("아직 대기중인 고객수 : %d\n\n", customers - served_customers); fprintf(fp, "\n[마감시간까지의 통계 출력]\n"); fprintf(fp, "서비스를 받은 고객수 : %d명\n", served_customers); fprintf(fp, "전체 대기 시간 : %d분\n", waited_time); fprintf(fp, "1인당 평군 대기 시간 : %f분\n", (double)waited_time / served_customers); fprintf(fp, "아직 대기중인 고객수 : %d\n\n", customers - served_customers); for (i = serverQueue.front + 1; i <= serverQueue.rear; i++) { printf("-> [%d번 서버님]\n", serverQueue.queue[i].id); printf("총 일한 시간 : %d분\n", serverQueue.queue[i].service_total_time); printf("총 대기 시간 : %d분\n", serverQueue.queue[i].waited_time); fprintf(fp, "-> [%d번 서버님]\n", serverQueue.queue[i].id); fprintf(fp, "총 일한 시간 : %d분\n", serverQueue.queue[i].service_total_time); fprintf(fp, "총 대기 시간 : %d분\n", serverQueue.queue[i].waited_time); if (serverQueue.queue[i].customerIDserving.id > -1) { // 서비스 받는 고객이 있음! if (serverQueue.queue[i].service_time > 0) { printf("마감시간이므로 고객 %d님의 남은 업무 %d분은 다음 날로 넘기겠습니다!\n", serverQueue.queue[i].customerIDserving.id, serverQueue.queue[i].service_time); fprintf(fp, "마감시간이므로 고객 %d님의 남은 업무 %d분은 다음 날로 넘기겠습니다!\n", serverQueue.queue[i].customerIDserving.id, serverQueue.queue[i].service_time); } else { printf("현재 시간에 정확히 끝남!\n"); fprintf(fp, "현재 시간에 정확히 끝남!\n"); } } printf("\n"); fprintf(fp, "\n"); } } // 시뮬레이션 프로그램 void main() { int i; // 루프용 변수 fopen_s(&fp, "result.txt", "w"); // 서버들 생성 serverCnt = MAX_SERVER_SIZE; ServerElement serverElement[MAX_SERVER_SIZE]; for (i = 0; i < serverCnt; i++) { serverElement[i].id = i + 1; serverElement[i].waited_time = 0; serverElement[i].service_total_time = 0; serverElement[i].service_time = 0; serverElement[i].waitingQueue.front = 0; serverElement[i].waitingQueue.rear = 0; enqueueServer(&serverQueue, serverElement[i]); } while (clock++ < duration) { printf("\n[현재 시각 알림]\n현재시각 : %d분\n\n", clock); fprintf(fp, "\n[현재 시각 알림]\n현재시각 : %d분\n\n", clock); for (i = 0; i < 3; i++) { if (is_customer_arrived()) { printf("[고객 알림]\n"); fprintf(fp, "[고객 알림]\n"); int insertFlag = FALSE; // 첫 번째 서버부터 사람들은 탐색함. 왜냐하면 그 순으로 가깝기 때문이다. // 첫번째로, 자기가 서비스를 받을 수 있으면 그 줄로 감 for (i = serverQueue.front + 1; i <= serverQueue.rear; i++) { if (serverQueue.queue[i].customerIDserving.id == -1 && isEmpty(&serverQueue.queue[i].waitingQueue)) { insert_customer(clock, &serverQueue.queue[i].waitingQueue); printf("고객%d : %d번 서버에 줄도 없고 서비스 하지 않네.\n", serverQueue.queue[i].waitingQueue.queue[serverQueue.queue[i].waitingQueue.rear].id, i); fprintf(fp, "고객%d : %d번 서버에 줄도 없고 서비스 하지 않네.\n", serverQueue.queue[i].waitingQueue.queue[serverQueue.queue[i].waitingQueue.rear].id, i); insertFlag = TRUE; break; } } // 두번째로 전부 서비스 중인 경우, 제일 적은 줄로 이동함. if (!insertFlag) { int min = 0; int minIndex = 0; for (i = serverQueue.front + 1; i <= serverQueue.rear; i++) { if (serverQueue.queue[i].waitingQueue.rear - serverQueue.queue[i].waitingQueue.front <= min) { min = serverQueue.queue[i].waitingQueue.rear - serverQueue.queue[i].waitingQueue.front; minIndex = i; break; } } insert_customer(clock, &serverQueue.queue[minIndex].waitingQueue); printf("고객%d : %d번 서버에 줄이 %d명으로 제일 적네. 저기로 가야겠다.\n", serverQueue.queue[minIndex].waitingQueue.queue[serverQueue.queue[minIndex].waitingQueue.rear].id, minIndex, min); fprintf(fp, "고객%d : %d번 서버에 줄이 %d명으로 제일 적네. 저기로 가야겠다.\n", serverQueue.queue[minIndex].waitingQueue.queue[serverQueue.queue[minIndex].waitingQueue.rear].id, minIndex, min); } printf("==================================\n"); fprintf(fp, "==================================\n"); } } for (i = serverQueue.front + 1; i <= serverQueue.rear; i++) { printf("[%d번 서버 현황]\n", serverQueue.queue[i].id); fprintf(fp, "[%d번 서버 현황]\n", serverQueue.queue[i].id); if (serverQueue.queue[i].service_time > 0) { if (serverQueue.queue[i].customerIDserving.id > -1) { printf("아직 %d번 고객님의 서비스가 끝나지 않았습니다!\n", serverQueue.queue[i].customerIDserving.id); fprintf(fp, "아직 %d번 고객님의 서비스가 끝나지 않았습니다!\n", serverQueue.queue[i].customerIDserving.id); } serverQueue.queue[i].service_time--; serverQueue.queue[i].service_total_time++; } else { // 현재 서비스가 끝남. // 현재 줄에 아무도 없고 양 옆 줄에 대기 사람이 있으면 불러들임! if (isEmpty(&serverQueue.queue[i].waitingQueue)) { if (i == serverQueue.front + 1) { // 맨 첫 번째 큐는 2번째 줄 확인하고 불러들임! if (!isEmpty(&serverQueue.queue[i + 1].waitingQueue)) { printf("%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); fprintf(fp, "%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); enqueue(&serverQueue.queue[i].waitingQueue, dequeue(&serverQueue.queue[i + 1].waitingQueue)); } } else if (i == serverQueue.rear) { // 맨 마지막 큐는 그 전 줄 확인하고 불러들임! if (!isEmpty(&serverQueue.queue[i - 1].waitingQueue)) { printf("%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); fprintf(fp, "%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); enqueue(&serverQueue.queue[i].waitingQueue, dequeue(&serverQueue.queue[i - 1].waitingQueue)); } } else { // 그 둘이 아니라면, 랜덤으로 양 옆에 불러옴! if (!isEmpty(&serverQueue.queue[i - 1].waitingQueue)) { printf("%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); fprintf(fp, "%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); enqueue(&serverQueue.queue[i].waitingQueue, dequeue(&serverQueue.queue[i - 1].waitingQueue)); } else if (!isEmpty(&serverQueue.queue[i + 1].waitingQueue)) { printf("%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); fprintf(fp, "%d 서버 : 옆 손님 이쪽으로 와주세요~\n", i); enqueue(&serverQueue.queue[i].waitingQueue, dequeue(&serverQueue.queue[i + 1].waitingQueue)); } } } serverQueue.queue[i].service_time = remove_customer(&serverQueue.queue[i]); if (serverQueue.queue[i].service_time == 0) { printf("고객이 오기를 대기 중입니다!\n"); fprintf(fp, "고객이 오기를 대기 중입니다!\n"); serverQueue.queue[i].waited_time++; serverQueue.queue[i].customerIDserving.id = -1; } } printf("\n"); fprintf(fp, "\n"); } } // 잔여 고객을 모두 돌려보낸다. print_stat(); fclose(fp); } | cs |