mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-21 21:11:57 +03:00
feat: add non_preemptive_priority_scheduling
in Process Scheduling Algorithm (#968)
* Added NonPreemptivePriorityScheduling * updating DIRECTORY.md * Added documentation and tests * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Left out documentation and suggested changes * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: David Leal <halfpacho@gmail.com> * test case added with assert.h * Update process_scheduling_algorithms/non_preemptive_priority_scheduling.c Co-authored-by: Taj <tjgurwara99@users.noreply.github.com> * typedef | Snake Case naming * chore: apply suggestions from code review Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <halfpacho@gmail.com> Co-authored-by: Taj <tjgurwara99@users.noreply.github.com>
This commit is contained in:
parent
856168384d
commit
136dee84e7
@ -318,6 +318,9 @@
|
||||
* [Simpsons 1 3Rd Rule](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/simpsons_1_3rd_rule.c)
|
||||
* [Variance](https://github.com/TheAlgorithms/C/blob/HEAD/numerical_methods/variance.c)
|
||||
|
||||
## Process Scheduling Algorithms
|
||||
* [Non Preemptive Priority Scheduling](https://github.com/TheAlgorithms/C/blob/master/process_scheduling_algorithms/non_preemptive_priority_scheduling.c)
|
||||
|
||||
## Project Euler
|
||||
* Problem 1
|
||||
* [Sol1](https://github.com/TheAlgorithms/C/blob/HEAD/project_euler/problem_1/sol1.c)
|
||||
|
@ -0,0 +1,369 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* [Non-Preemptive Priority
|
||||
* Scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing))
|
||||
* is a scheduling algorithm that selects the tasks to execute based on
|
||||
* priority.
|
||||
*
|
||||
* @details
|
||||
* In this algorithm, processes are executed according to their
|
||||
* priority. The process with the highest priority is to be executed first and
|
||||
* so on. In this algorithm, a variable is maintained known as the time quantum.
|
||||
* The length of the time quantum is decided by the user. The process which is
|
||||
* being executed is interrupted after the expiration of the time quantum and
|
||||
* the next process with the highest priority is executed. This cycle of
|
||||
* interrupting the process after every time quantum and resuming the next
|
||||
* process with the highest priority continues until all the processes have
|
||||
* been executed.
|
||||
* @author [Aryan Raj](https://github.com/aryaraj132)
|
||||
*/
|
||||
#include <assert.h> /// for assert
|
||||
#include <stdbool.h> /// for boolean data type
|
||||
#include <stdio.h> /// for IO operations (`printf`)
|
||||
#include <stdlib.h> /// for memory allocation eg: `malloc`, `realloc`, `free`, `exit`
|
||||
/**
|
||||
* @brief Structure to represent a process
|
||||
*/
|
||||
typedef struct node {
|
||||
int ID; ///< ID of the process node
|
||||
int AT; ///< Arrival Time of the process node
|
||||
int BT; ///< Burst Time of the process node
|
||||
int priority; ///< Priority of the process node
|
||||
int CT; ///< Completion Time of the process node
|
||||
int WT; ///< Waiting Time of the process node
|
||||
int TAT; ///< Turn Around Time of the process node
|
||||
struct node *next; ///< pointer to the node
|
||||
} node;
|
||||
|
||||
/**
|
||||
* @brief To insert a new process in the queue
|
||||
* @param root pointer to the head of the queue
|
||||
* @param id process ID
|
||||
* @param at arrival time
|
||||
* @param bt burst time
|
||||
* @param prior priority of the process
|
||||
* @returns void
|
||||
*/
|
||||
void insert(node **root, int id, int at, int bt, int prior)
|
||||
{
|
||||
// create a new node and initialize it
|
||||
node *new = (node *)malloc(sizeof(node));
|
||||
node *ptr = *root;
|
||||
new->ID = id;
|
||||
new->AT = at;
|
||||
new->BT = bt;
|
||||
new->priority = prior;
|
||||
new->next = NULL;
|
||||
new->CT = 0;
|
||||
new->WT = 0;
|
||||
new->TAT = 0;
|
||||
// if the root is null, make the new node the root
|
||||
if (*root == NULL)
|
||||
{
|
||||
*root = new;
|
||||
return;
|
||||
}
|
||||
// else traverse to the end of the queue and insert the new node there
|
||||
while (ptr->next != NULL)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
ptr->next = new;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* @brief To delete a process from the queue
|
||||
* @param root pointer to the head of the queue
|
||||
* @param id process ID
|
||||
* @returns void
|
||||
*/
|
||||
void delete(node **root, int id)
|
||||
{
|
||||
node *ptr = *root, *prev;
|
||||
// if the root is null, return
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if the root is the process to be deleted, make the next node the root
|
||||
if (ptr->ID == id)
|
||||
{
|
||||
*root = ptr->next;
|
||||
free(ptr);
|
||||
return;
|
||||
}
|
||||
// else traverse the queue and delete the process
|
||||
while (ptr != NULL && ptr->ID != id)
|
||||
{
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
prev->next = ptr->next;
|
||||
free(ptr);
|
||||
}
|
||||
/**
|
||||
* @brief To show the process queue
|
||||
* @param head pointer to the head of the queue
|
||||
* @returns void
|
||||
*/
|
||||
void show_list(node *head)
|
||||
{
|
||||
printf("Process Priority AT BT CT TAT WT \n");
|
||||
while (head != NULL)
|
||||
{
|
||||
printf("P%d. %d %d %d %d %d %d \n", head->ID, head->priority, head->AT,
|
||||
head->BT, head->CT, head->TAT, head->WT);
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief To length process queue
|
||||
* @param root pointer to the head of the queue
|
||||
* @returns int total length of the queue
|
||||
*/
|
||||
int l_length(node **root)
|
||||
{
|
||||
int count = 0;
|
||||
node *ptr = *root;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
count++;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/**
|
||||
* @brief To update the completion time, turn around time and waiting time of
|
||||
* the processes
|
||||
* @param root pointer to the head of the queue
|
||||
* @param id process ID
|
||||
* @param ct current time
|
||||
* @param wt waiting time
|
||||
* @param tat turn around time
|
||||
* @returns void
|
||||
*/
|
||||
void update(node **root, int id, int ct, int wt, int tat)
|
||||
{
|
||||
node *ptr = *root;
|
||||
// If process to be updated is head node
|
||||
if (ptr != NULL && ptr->ID == id)
|
||||
{
|
||||
if (ct != 0)
|
||||
{
|
||||
ptr->CT = ct;
|
||||
}
|
||||
if (wt != 0)
|
||||
{
|
||||
ptr->WT = wt;
|
||||
}
|
||||
if (tat != 0)
|
||||
{
|
||||
ptr->TAT = tat;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// else traverse the queue and update the values
|
||||
while (ptr != NULL && ptr->ID != id)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ct != 0)
|
||||
{
|
||||
ptr->CT = ct;
|
||||
}
|
||||
if (wt != 0)
|
||||
{
|
||||
ptr->WT = wt;
|
||||
}
|
||||
if (tat != 0)
|
||||
{
|
||||
ptr->TAT = tat;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* @brief To compare the priority of two processes based on their arrival time
|
||||
* and priority
|
||||
* @param a pointer to the first process
|
||||
* @param b pointer to the second process
|
||||
* @returns true if the priority of the first process is greater than the
|
||||
* the second process
|
||||
* @returns false if the priority of the first process is NOT greater than the
|
||||
* second process
|
||||
*/
|
||||
bool compare(node *a, node *b)
|
||||
{
|
||||
if (a->AT == b->AT)
|
||||
{
|
||||
return a->priority < b->priority;
|
||||
}
|
||||
else
|
||||
{
|
||||
return a->AT < b->AT;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief To calculate the average completion time of all the processes
|
||||
* @param root pointer to the head of the queue
|
||||
* @returns float average completion time
|
||||
*/
|
||||
float calculate_ct(node **root)
|
||||
{
|
||||
// calculate the total completion time of all the processes
|
||||
node *ptr = *root, *prior, *rpt;
|
||||
int ct = 0, i, time = 0;
|
||||
int n = l_length(root);
|
||||
float avg, sum = 0;
|
||||
node *duproot = NULL;
|
||||
// create a duplicate queue
|
||||
while (ptr != NULL)
|
||||
{
|
||||
insert(&duproot, ptr->ID, ptr->AT, ptr->BT, ptr->priority);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
ptr = duproot;
|
||||
rpt = ptr->next;
|
||||
// sort the queue based on the arrival time and priority
|
||||
while (rpt != NULL)
|
||||
{
|
||||
if (!compare(ptr, rpt))
|
||||
{
|
||||
ptr = rpt;
|
||||
}
|
||||
rpt = rpt->next;
|
||||
}
|
||||
// ptr is the process to be executed first.
|
||||
ct = ptr->AT + ptr->BT;
|
||||
time = ct;
|
||||
sum += ct;
|
||||
// update the completion time, turn around time and waiting time of the
|
||||
// process
|
||||
update(root, ptr->ID, ct, 0, 0);
|
||||
delete (&duproot, ptr->ID);
|
||||
// repeat the process until all the processes are executed
|
||||
for (i = 0; i < n - 1; i++)
|
||||
{
|
||||
ptr = duproot;
|
||||
while (ptr != NULL && ptr->AT > time)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
rpt = ptr->next;
|
||||
while (rpt != NULL)
|
||||
{
|
||||
if (rpt->AT <= time)
|
||||
{
|
||||
if (rpt->priority < ptr->priority)
|
||||
{
|
||||
ptr = rpt;
|
||||
}
|
||||
}
|
||||
rpt = rpt->next;
|
||||
}
|
||||
ct += ptr->BT;
|
||||
time += ptr->BT;
|
||||
sum += ct;
|
||||
update(root, ptr->ID, ct, 0, 0);
|
||||
delete (&duproot, ptr->ID);
|
||||
}
|
||||
avg = sum / n;
|
||||
return avg;
|
||||
}
|
||||
/**
|
||||
* @brief To calculate the average turn around time of all the processes
|
||||
* @param root pointer to the head of the queue
|
||||
* @returns float average turn around time
|
||||
*/
|
||||
float calculate_tat(node **root)
|
||||
{
|
||||
float avg, sum = 0;
|
||||
int n = l_length(root);
|
||||
node *ptr = *root;
|
||||
// calculate the completion time if not already calculated
|
||||
if (ptr->CT == 0)
|
||||
{
|
||||
calculate_ct(root);
|
||||
}
|
||||
// calculate the total turn around time of all the processes
|
||||
while (ptr != NULL)
|
||||
{
|
||||
ptr->TAT = ptr->CT - ptr->AT;
|
||||
sum += ptr->TAT;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
avg = sum / n;
|
||||
return avg;
|
||||
}
|
||||
/**
|
||||
* @brief To calculate the average waiting time of all the processes
|
||||
* @param root pointer to the head of the queue
|
||||
* @returns float average waiting time
|
||||
*/
|
||||
float calculate_wt(node **root)
|
||||
{
|
||||
float avg, sum = 0;
|
||||
int n = l_length(root);
|
||||
node *ptr = *root;
|
||||
// calculate the completion if not already calculated
|
||||
if (ptr->CT == 0)
|
||||
{
|
||||
calculate_ct(root);
|
||||
}
|
||||
// calculate the total waiting time of all the processes
|
||||
while (ptr != NULL)
|
||||
{
|
||||
ptr->WT = (ptr->TAT - ptr->BT);
|
||||
sum += ptr->WT;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
avg = sum / n;
|
||||
return avg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test()
|
||||
{
|
||||
// Entered processes
|
||||
// printf("ID Priority Arrival Time Burst Time \n");
|
||||
// printf("1 0 5 1 \n");
|
||||
// printf("2 1 4 2 \n");
|
||||
// printf("3 2 3 3 \n");
|
||||
// printf("4 3 2 4 \n");
|
||||
// printf("5 4 1 5 \n");
|
||||
|
||||
node *root = NULL;
|
||||
insert(&root, 1, 0, 5, 1);
|
||||
insert(&root, 2, 1, 4, 2);
|
||||
insert(&root, 3, 2, 3, 3);
|
||||
insert(&root, 4, 3, 2, 4);
|
||||
insert(&root, 5, 4, 1, 5);
|
||||
float avgCT = calculate_ct(&root);
|
||||
float avgTAT = calculate_tat(&root);
|
||||
float avgWT = calculate_wt(&root);
|
||||
assert(avgCT == 11);
|
||||
assert(avgTAT == 9);
|
||||
assert(avgWT == 6);
|
||||
printf("[+] All tests have successfully passed!\n");
|
||||
// printf("Average Completion Time is : %f \n", calculate_ct(&root));
|
||||
// printf("Average Turn Around Time is : %f \n", calculate_tat(&root));
|
||||
// printf("Average Waiting Time is : %f \n", calculate_wt(&root));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
test(); // run self-test implementations
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user