Assignment question, submitted solution and professor's solution
This commit is contained in:
parent
4768ba2a35
commit
f496f98edf
BIN
Assignment 2.pdf
Normal file
BIN
Assignment 2.pdf
Normal file
Binary file not shown.
725
ass2.c
Normal file
725
ass2.c
Normal file
@ -0,0 +1,725 @@
|
||||
/* License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
|
||||
*
|
||||
* Assignment 2 - Discrete Simulation
|
||||
* Manish
|
||||
* Student Login: *****
|
||||
*
|
||||
* Compile it as:
|
||||
* gcc -Wall -std=c11 -o ass2 ass2.c
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum category
|
||||
{
|
||||
TOURIST = 0,
|
||||
BUSINESS = 1,
|
||||
};
|
||||
|
||||
typedef struct event
|
||||
{
|
||||
// 0 for arrival 1+ for unique server ids
|
||||
int id;
|
||||
double time;
|
||||
int class; // 0 for tourist and 1 for business
|
||||
// service time for customer arrival and busy time for servers
|
||||
double duration;
|
||||
} event;
|
||||
|
||||
// customers_queue is dynamically scaled
|
||||
typedef struct customers_queue
|
||||
{
|
||||
int first;
|
||||
int next;
|
||||
int size; // memory in use
|
||||
int capacity; // memory allocated to queue
|
||||
event* queue;
|
||||
} customers_queue;
|
||||
|
||||
typedef struct id_busy
|
||||
{
|
||||
int id; // unique server ID
|
||||
double busy; // time server was busy
|
||||
} id_busy;
|
||||
|
||||
// servers_queue are dynamically infantilized than not re-scaled
|
||||
typedef struct servers_queue
|
||||
{
|
||||
int first;
|
||||
int next;
|
||||
int available;
|
||||
int capacity;
|
||||
id_busy* queue;
|
||||
} servers_queue;
|
||||
|
||||
// Used as temporary storages for processing
|
||||
event arrival;
|
||||
event customer_in_queue;
|
||||
id_busy server;
|
||||
|
||||
// Dynamically initialized than not re-scaled
|
||||
event* heap;
|
||||
int heap_size = 0;
|
||||
|
||||
customers_queue business_q;
|
||||
customers_queue tourist_q;
|
||||
|
||||
servers_queue business_servers;
|
||||
servers_queue tourist_servers;
|
||||
|
||||
bool dummy_arrival(const event* arrival);
|
||||
int read_next_arrival(FILE* file, event* e);
|
||||
void read_back_next_arrival(FILE* file, event* e);
|
||||
void read_front_next_arrival(FILE* file, event* e);
|
||||
void shiftdown(int i);
|
||||
void shiftup(int i);
|
||||
void swap(event* i, event* j);
|
||||
|
||||
event dequeue_customers(customers_queue* q);
|
||||
void enqueue_customers(customers_queue* q, const event* e);
|
||||
/* Used for sorting servers by id before printing output
|
||||
* Heap sort is used since we do not need stable sorting as all ids are unique
|
||||
* and heap sort sorts in place therefore require less memory than merge sort
|
||||
*/
|
||||
void server_shiftdown(servers_queue* heap, int i);
|
||||
void server_makeheap(servers_queue* q);
|
||||
void server_sort(servers_queue* q);
|
||||
void server_swap(id_busy* i, id_busy* j);
|
||||
|
||||
id_busy dequeue_servers(servers_queue* q);
|
||||
void enqueue_servers(servers_queue* q, const id_busy* s);
|
||||
void free_server(servers_queue* q);
|
||||
|
||||
int max(int i, int j);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("Enter file name: ");
|
||||
char filename[257];
|
||||
// Assuming filename/file path won't be longer than 256 characters
|
||||
scanf("%256s", filename);
|
||||
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (!file)
|
||||
{
|
||||
perror(filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (int pass = 1; pass <= 2; pass++)
|
||||
{
|
||||
rewind(file); // move file pointer back to beginning
|
||||
|
||||
// Read no. of business and & tourist servers
|
||||
fscanf(
|
||||
file,
|
||||
"%d %d",
|
||||
&business_servers.available,
|
||||
&tourist_servers.available);
|
||||
|
||||
arrival.id = 0;
|
||||
if (read_next_arrival(file, &arrival) == EOF)
|
||||
{
|
||||
fprintf(stderr, "Error in reading 1st arrival. Exiting\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// INITIALIZE/RESET VARIABLES
|
||||
heap = malloc(
|
||||
sizeof(event)
|
||||
* (1 + business_servers.available + tourist_servers.available));
|
||||
|
||||
business_servers.first = 0;
|
||||
business_servers.next = 0;
|
||||
business_servers.capacity = business_servers.available;
|
||||
business_servers.queue = malloc(
|
||||
sizeof(event) * business_servers.capacity);
|
||||
|
||||
tourist_servers.first = 0;
|
||||
tourist_servers.next = 0;
|
||||
tourist_servers.capacity = tourist_servers.available;
|
||||
tourist_servers.queue = malloc(
|
||||
sizeof(event) * tourist_servers.capacity);
|
||||
|
||||
if (heap == NULL
|
||||
|| business_servers.queue == NULL
|
||||
|| tourist_servers.queue == NULL)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Failed to allocate memory for all data structures\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
business_q.first = 0;
|
||||
business_q.next = 0;
|
||||
business_q.size = 0;
|
||||
business_q.capacity = 0;
|
||||
// Memory is allocated only if needed
|
||||
business_q.queue = NULL;
|
||||
tourist_q.first = 0;
|
||||
tourist_q.next = 0;
|
||||
tourist_q.size = 0;
|
||||
tourist_q.capacity = 0;
|
||||
// Memory is allocated only if needed
|
||||
tourist_q.queue = NULL;
|
||||
|
||||
for (int i = 0; i < business_servers.capacity; i++)
|
||||
{
|
||||
business_servers.queue[i].id = i + 1;
|
||||
business_servers.queue[i].busy = 0;
|
||||
}
|
||||
for (int i = 0; i < tourist_servers.capacity; i++)
|
||||
{
|
||||
tourist_servers.queue[i].id = i + business_servers.capacity + 1;
|
||||
tourist_servers.queue[i].busy = 0;
|
||||
}
|
||||
|
||||
heap[heap_size++] = arrival;
|
||||
|
||||
// Statistics Variables
|
||||
double time = 0;
|
||||
|
||||
int max_q_length = 0;
|
||||
|
||||
int no_of_business_customers = 0;
|
||||
double business_service_time = 0;
|
||||
double business_q_time = 0;
|
||||
int max_business_q_length = 0;
|
||||
|
||||
int no_of_tourist_customers = 0;
|
||||
double tourist_service_time = 0;
|
||||
double tourist_q_time = 0;
|
||||
int max_tourist_q_length = 0;
|
||||
|
||||
// MAIN LOOP
|
||||
while (heap_size > 0)
|
||||
{
|
||||
time = heap[0].time;
|
||||
if (heap[0].id == 0) // Arrival
|
||||
{
|
||||
if (heap[0].class == TOURIST)
|
||||
{
|
||||
no_of_tourist_customers++;
|
||||
tourist_service_time += heap[0].duration;
|
||||
if (tourist_servers.available)
|
||||
{
|
||||
// Time when server will finish serving
|
||||
heap[0].time += heap[0].duration;
|
||||
server = dequeue_servers(&tourist_servers);
|
||||
heap[0].id = server.id;
|
||||
// Total busy time of server
|
||||
heap[0].duration += server.busy;
|
||||
shiftdown(0);
|
||||
read_back_next_arrival(file, &arrival);
|
||||
}
|
||||
/* Available/free business servers will serve tourist
|
||||
* customer in 2nd pass if no business customer in q
|
||||
* NOTE: free server implies business_q is empty
|
||||
*/
|
||||
else if (pass == 2 && business_servers.available)
|
||||
{
|
||||
// Time when server will finish serving
|
||||
heap[0].time += heap[0].duration;
|
||||
server = dequeue_servers(&business_servers);
|
||||
heap[0].id = server.id;
|
||||
// Total busy time of server
|
||||
heap[0].duration += server.busy;
|
||||
shiftdown(0);
|
||||
read_back_next_arrival(file, &arrival);
|
||||
}
|
||||
// All relevant servers busy, add to tourist customers queue
|
||||
else
|
||||
{
|
||||
enqueue_customers(&tourist_q, &heap[0]);
|
||||
max_tourist_q_length = max(
|
||||
max_tourist_q_length, tourist_q.size);
|
||||
max_q_length = max(
|
||||
max_q_length, tourist_q.size + business_q.size);
|
||||
read_front_next_arrival(file, &arrival);
|
||||
}
|
||||
}
|
||||
else if (heap[0].class == BUSINESS)
|
||||
{
|
||||
no_of_business_customers++;
|
||||
business_service_time += heap[0].duration;
|
||||
if (business_servers.available)
|
||||
{
|
||||
// Time when server will finish serving
|
||||
heap[0].time += heap[0].duration;
|
||||
server = dequeue_servers(&business_servers);
|
||||
heap[0].id = server.id;
|
||||
// Total busy time of server
|
||||
heap[0].duration += server.busy;
|
||||
shiftdown(0);
|
||||
read_back_next_arrival(file, &arrival);
|
||||
}
|
||||
// All relevant servers busy, add to tourist customers queue
|
||||
else
|
||||
{
|
||||
enqueue_customers(&business_q, &heap[0]);
|
||||
max_business_q_length = max(
|
||||
max_business_q_length, business_q.size);
|
||||
max_q_length = max(
|
||||
max_q_length, tourist_q.size + business_q.size);
|
||||
read_front_next_arrival(file, &arrival);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Impossible scenario: Event = Arrival but Class = %d",
|
||||
heap[0].class);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if ( // Business server finished serving
|
||||
heap[0].id >= 1 && heap[0].id <= business_servers.capacity)
|
||||
{
|
||||
if (business_q.size > 0) // Customers waiting in queue
|
||||
{
|
||||
customer_in_queue = dequeue_customers(&business_q);
|
||||
business_q_time += time - customer_in_queue.time;
|
||||
// Time when server will finish serving
|
||||
heap[0].time += customer_in_queue.duration;
|
||||
// Total busy time of server
|
||||
heap[0].duration += customer_in_queue.duration;
|
||||
shiftdown(0);
|
||||
}
|
||||
/* Freed business servers will serve tourist customer
|
||||
* 2nd pass if no business customer in q
|
||||
*/
|
||||
else if (pass == 2 && tourist_q.size > 0)
|
||||
{
|
||||
customer_in_queue = dequeue_customers(&tourist_q);
|
||||
// Time when server will finish serving
|
||||
tourist_q_time += time - customer_in_queue.time;
|
||||
heap[0].time += customer_in_queue.duration;
|
||||
// Total busy time of server
|
||||
heap[0].duration += customer_in_queue.duration;
|
||||
shiftdown(0);
|
||||
}
|
||||
else // free server at heap[0] and enqueue to business_servers
|
||||
free_server(&business_servers);
|
||||
}
|
||||
else if (
|
||||
heap[0].id > business_servers.capacity
|
||||
&& heap[0].id <= (business_servers.capacity
|
||||
+ tourist_servers.capacity))
|
||||
{
|
||||
if (tourist_q.size > 0) // Customers waiting in queue
|
||||
{
|
||||
customer_in_queue = dequeue_customers(&tourist_q);
|
||||
// Time when server will finish serving
|
||||
tourist_q_time += time - customer_in_queue.time;
|
||||
heap[0].time += customer_in_queue.duration;
|
||||
// Total busy time of server
|
||||
heap[0].duration += customer_in_queue.duration;
|
||||
shiftdown(0);
|
||||
}
|
||||
else // free server at heap[0] and enqueue to tourist_servers
|
||||
free_server(&tourist_servers);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Impossible scenario Heap[0].id = %d is out of range\n",
|
||||
heap[0].id);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// COMPUTE REMAINING STATISTICS FROM TRACKED STATISTICS
|
||||
int total_customers = (
|
||||
no_of_business_customers + no_of_tourist_customers);
|
||||
double avg_q_time = (
|
||||
(business_q_time + tourist_q_time) / total_customers);
|
||||
double avg_q_length = ((business_q_time + tourist_q_time) / time);
|
||||
double avg_service_time = (
|
||||
(business_service_time
|
||||
+ business_q_time
|
||||
+ tourist_q_time
|
||||
+ tourist_service_time)
|
||||
/ total_customers);
|
||||
|
||||
double avg_business_q_time = (
|
||||
business_q_time / no_of_business_customers);
|
||||
double avg_business_q_length = (business_q_time / time);
|
||||
double avg_business_service_time = (
|
||||
(business_service_time + business_q_time)
|
||||
/ no_of_business_customers);
|
||||
|
||||
double avg_tourist_q_time = (tourist_q_time / no_of_tourist_customers);
|
||||
double avg_tourist_q_length = (tourist_q_time / time);
|
||||
double avg_tourist_service_time = (
|
||||
(tourist_service_time + tourist_q_time) / no_of_tourist_customers);
|
||||
|
||||
// SIMULATION OUTPUT/PRINT SIMULATION STATISTICS
|
||||
char pass_title[80];
|
||||
if (pass == 1)
|
||||
strncpy(
|
||||
pass_title,
|
||||
"Pass 1: Business servers exclusively serve business class",
|
||||
80);
|
||||
else if (pass == 2)
|
||||
strncpy(
|
||||
pass_title,
|
||||
"Pass 2: Idle business servers may serve tourist class",
|
||||
80);
|
||||
|
||||
printf(
|
||||
"%s\n\n"
|
||||
"%-50s % 5d\n"
|
||||
"%-50s % 8.2lf\n\n"
|
||||
"%s\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 5d\n\n"
|
||||
"%s\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 5d\n\n"
|
||||
"%s\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 8.2lf\n"
|
||||
"%-50s % 5d\n"
|
||||
"\n",
|
||||
pass_title,
|
||||
"Number of people served: ",
|
||||
total_customers,
|
||||
"Time last service is completed: ",
|
||||
time,
|
||||
"Business class customers: ",
|
||||
"Average total service time: ",
|
||||
avg_business_service_time,
|
||||
"Average total time in queue: ",
|
||||
avg_business_q_time,
|
||||
"Ave length of queue: ",
|
||||
avg_business_q_length,
|
||||
"Maximum number queued: ",
|
||||
max_business_q_length,
|
||||
"Tourist class customers:",
|
||||
"Average total service time: ",
|
||||
avg_tourist_service_time,
|
||||
"Average total time in queue: ",
|
||||
avg_tourist_q_time,
|
||||
"Ave length of queue: ",
|
||||
avg_tourist_q_length,
|
||||
"Maximum number queued: ",
|
||||
max_tourist_q_length,
|
||||
"All customers:",
|
||||
"Average total service time: ",
|
||||
avg_service_time,
|
||||
"Average total time in queue: ",
|
||||
avg_q_time,
|
||||
"Ave length of queue: ",
|
||||
avg_q_length,
|
||||
"Maximum number queued: ",
|
||||
max_q_length);
|
||||
|
||||
// Sort servers by ID before printing
|
||||
server_sort(&business_servers);
|
||||
printf("Business class servers:\n");
|
||||
for (int i = 0; i < business_servers.capacity; i++)
|
||||
printf(
|
||||
"Total idle time for business class server %3d: %13.2lf\n",
|
||||
business_servers.queue[i].id,
|
||||
time - business_servers.queue[i].busy);
|
||||
|
||||
// Sort servers by ID before printing
|
||||
server_sort(&tourist_servers);
|
||||
printf("\nTourist class servers:\n");
|
||||
for (int i = 0; i < tourist_servers.capacity; i++)
|
||||
printf(
|
||||
"Total idle time for tourist class server %3d: %14.2lf\n",
|
||||
tourist_servers.queue[i].id - business_servers.capacity,
|
||||
time - tourist_servers.queue[i].busy);
|
||||
|
||||
printf("\n\n\n");
|
||||
|
||||
// FREE DYNAMICALLY ALLOCATED MEMORY
|
||||
free(heap);
|
||||
free(business_servers.queue);
|
||||
free(tourist_servers.queue);
|
||||
free(business_q.queue);
|
||||
free(tourist_q.queue);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool dummy_arrival(const event* arrival)
|
||||
{
|
||||
return (
|
||||
arrival->time == 0 && arrival->duration == 0);
|
||||
}
|
||||
|
||||
int read_next_arrival(FILE* file, event* e)
|
||||
{
|
||||
return fscanf(file, "%lf %d %lf", &e->time, &e->class, &e->duration);
|
||||
}
|
||||
|
||||
void read_back_next_arrival(FILE* file, event* e)
|
||||
{
|
||||
// WARNING: Potential BUG: dummy_arrival(e) gets old arrival or new?
|
||||
if (fscanf(file, "%lf %d %lf", &e->time, &e->class, &e->duration) != EOF
|
||||
&& dummy_arrival(e) == false)
|
||||
{
|
||||
heap[heap_size++] = *e;
|
||||
shiftup(heap_size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void read_front_next_arrival(FILE* file, event* e)
|
||||
{
|
||||
if (fscanf(file, "%lf %d %lf", &e->time, &e->class, &e->duration) != EOF
|
||||
&& dummy_arrival(e) == false)
|
||||
{
|
||||
heap[0] = *e;
|
||||
}
|
||||
else
|
||||
{ // Since dummy arrival or EOF reached, pop heap[0]
|
||||
swap(&heap[0], &heap[--heap_size]);
|
||||
}
|
||||
shiftdown(0);
|
||||
}
|
||||
|
||||
void shiftdown(int i)
|
||||
{
|
||||
int child = (i * 2) + 1; // left child
|
||||
if (child < heap_size) // has at least one child
|
||||
{
|
||||
if (child < heap_size - 1) // has both children
|
||||
{
|
||||
// if right child smaller
|
||||
if (heap[child].time > heap[child + 1].time)
|
||||
child++; // pick right child
|
||||
}
|
||||
if (heap[i].time > heap[child].time)
|
||||
{
|
||||
swap(&heap[i], &heap[child]);
|
||||
shiftdown(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shiftup(int i)
|
||||
{
|
||||
if (i == 0)
|
||||
return;
|
||||
int parent = (i - 1) / 2;
|
||||
if (heap[parent].time > heap[i].time)
|
||||
{
|
||||
swap(&heap[parent], &heap[i]);
|
||||
shiftup(parent);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(event* i, event* j)
|
||||
{
|
||||
event tmp = *i;
|
||||
*i = *j;
|
||||
*j = tmp;
|
||||
}
|
||||
|
||||
event dequeue_customers(customers_queue* q)
|
||||
{
|
||||
if (q->size-- == 0)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Impossible scenario: dequeue_customers when queue empty");
|
||||
exit(1);
|
||||
}
|
||||
event customer = q->queue[q->first++];
|
||||
q->first %= q->capacity;
|
||||
if (q->size < q->capacity / 4)
|
||||
{
|
||||
int new_capacity = (q->capacity / 2) + (q->capacity % 2);
|
||||
if (q->size != 0
|
||||
&& (q->first >= new_capacity || q->next >= new_capacity))
|
||||
{
|
||||
/* Original queue:
|
||||
* XX--------|-------XXX
|
||||
* OR
|
||||
* --------XX|XXX-------
|
||||
* OR
|
||||
* -----------|-XXXXX----
|
||||
* Where X has some number, - is empty place & | is new_capacity
|
||||
* Than, copy queue to next location and free old space
|
||||
*/
|
||||
event* new_q = malloc(sizeof(event) * new_capacity);
|
||||
if (new_q == NULL)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Failed to reallocate memory for customer_queue\n");
|
||||
exit(1);
|
||||
}
|
||||
int j = 0;
|
||||
for (int i = q->first; i != q->next; i = (i + 1) % q->capacity)
|
||||
{
|
||||
new_q[j++] = q->queue[i];
|
||||
}
|
||||
free(q->queue);
|
||||
q->queue = new_q;
|
||||
q->first = 0;
|
||||
q->next = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->queue = realloc(q->queue, sizeof(event) * new_capacity);
|
||||
if (q->queue == NULL) // Probably unnecessary since shrinking
|
||||
{
|
||||
fprintf(
|
||||
stderr, "Failed to reallocate memory for customer_queue\n");
|
||||
exit(1);
|
||||
}
|
||||
if (q->size == 0)
|
||||
{
|
||||
q->first = 0;
|
||||
q->next = 0;
|
||||
}
|
||||
}
|
||||
q->capacity = new_capacity;
|
||||
}
|
||||
return customer;
|
||||
}
|
||||
|
||||
void enqueue_customers(customers_queue* q, const event* e)
|
||||
{
|
||||
if (q->size == q->capacity) // Queue full
|
||||
{
|
||||
// Double queue and adjust pointers
|
||||
// max() for when no space allocated previously i.e. capacity == 0
|
||||
int new_capacity = max(q->capacity * 2, 1);
|
||||
q->queue = realloc(q->queue, sizeof(event) * new_capacity);
|
||||
if (q->queue == NULL)
|
||||
{
|
||||
fprintf(
|
||||
stderr, "Failed to reallocate memory for customer_queue\n");
|
||||
exit(1);
|
||||
}
|
||||
if (q->first != 0)
|
||||
{
|
||||
/* Original queue:
|
||||
* XXX|XXXXXXX
|
||||
* After realloc:
|
||||
* XX|XXXXXXXX----------
|
||||
* After this loop:
|
||||
* XX----------|XXXXXXXX
|
||||
* Where X has some number, - is empty place
|
||||
* and | is q->first pointer
|
||||
*/
|
||||
for (int i = q->first; i < q->capacity; i++)
|
||||
{
|
||||
q->queue[i + q->capacity] = q->queue[i];
|
||||
}
|
||||
q->first += q->capacity;
|
||||
}
|
||||
/// MISSING THIS CORNER CASE WAS CAUSE OF A MAJOR BUG
|
||||
else
|
||||
q->next = q->size;
|
||||
|
||||
q->capacity = new_capacity;
|
||||
}
|
||||
q->size++;
|
||||
q->queue[q->next++] = *e;
|
||||
q->next %= q->capacity;
|
||||
}
|
||||
|
||||
id_busy dequeue_servers(servers_queue* q)
|
||||
{
|
||||
if (q->available-- == 0)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"Impossible scenario: dequeue_servers when queue empty");
|
||||
exit(1);
|
||||
}
|
||||
server = q->queue[q->first++];
|
||||
q->first %= q->capacity;
|
||||
return server;
|
||||
}
|
||||
|
||||
void enqueue_servers(servers_queue* q, const id_busy* s)
|
||||
{
|
||||
if (q->available++ == q->capacity)
|
||||
{
|
||||
fprintf(
|
||||
stderr, "Impossible scenario: enqueue_servers when queue full");
|
||||
exit(1);
|
||||
}
|
||||
q->queue[q->next++] = *s;
|
||||
q->next %= q->capacity;
|
||||
}
|
||||
|
||||
void free_server(servers_queue* q)
|
||||
{
|
||||
server.id = heap[0].id;
|
||||
server.busy = heap[0].duration;
|
||||
enqueue_servers(q, &server);
|
||||
heap[0] = heap[--heap_size];
|
||||
shiftdown(0);
|
||||
}
|
||||
|
||||
int max(int i, int j)
|
||||
{
|
||||
return (i > j) ? i : j;
|
||||
}
|
||||
|
||||
void server_shiftdown(servers_queue* heap, int i)
|
||||
{
|
||||
int child = (i * 2) + 1; // left child
|
||||
if (child < heap->available) // has at least one child
|
||||
{
|
||||
if (child < heap->available - 1) // has both children
|
||||
{
|
||||
// if right child smaller
|
||||
if (heap->queue[child].id < heap->queue[child + 1].id)
|
||||
child++; // pick right child
|
||||
}
|
||||
if (heap->queue[i].id < heap->queue[child].id)
|
||||
{
|
||||
server_swap(&heap->queue[child], &heap->queue[i]);
|
||||
server_shiftdown(heap, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void server_makeheap(servers_queue* q)
|
||||
{
|
||||
// Shiftdown Method
|
||||
int shiftdowns_required = (q->capacity / 2)-1;
|
||||
for (int i = shiftdowns_required; i >= 0; i--)
|
||||
{
|
||||
server_shiftdown(q, i);
|
||||
}
|
||||
}
|
||||
|
||||
void server_sort(servers_queue* q)
|
||||
{
|
||||
server_makeheap(q);
|
||||
while(q->available > 0)
|
||||
{
|
||||
server_swap(q->queue, &q->queue[--q->available]);
|
||||
server_shiftdown(q, 0);
|
||||
}
|
||||
q->available = q->capacity;
|
||||
}
|
||||
|
||||
void server_swap(id_busy* i, id_busy* j)
|
||||
{
|
||||
id_busy tmp = *i;
|
||||
*i = *j;
|
||||
*j = tmp;
|
||||
}
|
Loading…
Reference in New Issue
Block a user