Shortest job first (SJF) or shortest job next, is a scheduling policy that selects the waiting process with the smallest execution time to execute next. SJN is a non-preemptive algorithm.
- Shortest Job first has the advantage of having a minimum average waiting time among all scheduling algorithms.
- It is a Greedy Algorithm.
- It may cause starvation if shorter processes keep coming. This problem can be solved using the concept of ageing.
- It is practically infeasible as Operating System may not know burst time and therefore may not sort them. While it is not possible to predict execution time, several methods can be used to estimate the execution time for a job, such as a weighted average of previous execution times. SJF can be used in specialized environments where accurate estimates of running time are available.
For example:
In the above example, since the arrival time of all the processes is 0, the execution order of the process is the ascending order of the burst time of the processes. The burst time is given by the column duration. Therefore, the execution order of the processes is given by:
P4 -> P1 -> P3 -> P2
One implementation for this algorithm has already been discussed in the article with the help of Naive Approach. In this article, the algorithm is implemented by using the concept of a segment tree.
Approach: The following is the approach used for the implementation of the shortest job first:
- As the name suggests, the shortest job first algorithm is an algorithm which executes the process whose burst time is least and has arrived before the current time. Therefore, in order to find the process which needs to be executed, sort all the processes from the given set of processes according to their arrival time. This ensures that the process with the shortest burst time which has arrived first is executed first.
-
Instead of finding the minimum burst time process among all the arrived processes by iterating the
whole struct array, the range minimum of the burst time of all the arrived processes upto the current time is calculated using segment tree. -
After selecting a process which needs to be executed, the completion time, turn around time and waiting time is calculated by using arrival time and burst time of the process. The formulae to calculate the respective times are:
-
Completion Time: Time at which process completes its execution.
-
Completion Time: Time at which process completes its execution.
Completion Time = Start Time + Burst Time
-
Turn Around Time: Time Difference between completion time and arrival time.
Turn Around Time = Completion Time – Arrival Time
-
Waiting Time(W.T): Time Difference between turn around time and burst time.
Waiting Time = Turn Around Time – Burst Time
- After calculating, the respective times are updated in the array and the burst time of the executed process is set to infinity in the segment tree base array so that it is not considered as the minimum burst time in the further queries.
Below is the implementation of the shortest job first using the concept of segment tree:
// C++ implementation of shortest job first // using the concept of segment tree #include <bits/stdc++.h> using namespace std;
#define ll long long #define z 1000000007 #define sh 100000 #define pb push_back #define pr(x) printf("%d ", x) struct util {
// Process ID
int id;
// Arrival time
int at;
// Burst time
int bt;
// Completion time
int ct;
// Turnaround time
int tat;
// Waiting time
int wt;
} // Array to store all the process information // by implementing the above struct util ar[sh + 1]; struct util1 {
// Process id
int p_id;
// burst time
int bt1;
}; util1 range; // Segment tree array to // process the queries in nlogn util1 tr[4 * sh + 5]; // To keep an account of where // a particular process_id is // in the segment tree base array int mp[sh + 1];
// Comparator function to sort the // struct array according to arrival time bool cmp(util a, util b)
{ if (a.at == b.at)
return a.id < b.id;
return a.at < b.at;
} // Function to update the burst time and process id // in the segment tree void update( int node, int st, int end,
int ind, int id1, int b_t)
{ if (st == end) {
tr[node].p_id = id1;
tr[node].bt1 = b_t;
return ;
}
int mid = (st + end) / 2;
if (ind <= mid)
update(2 * node, st, mid, ind, id1, b_t);
else
update(2 * node + 1, mid + 1, end, ind, id1, b_t);
if (tr[2 * node].bt1 < tr[2 * node + 1].bt1) {
tr[node].bt1 = tr[2 * node].bt1;
tr[node].p_id = tr[2 * node].p_id;
}
else {
tr[node].bt1 = tr[2 * node + 1].bt1;
tr[node].p_id = tr[2 * node + 1].p_id;
}
} // Function to return the range minimum of the burst time // of all the arrived processes using segment tree util1 query( int node, int st, int end, int lt, int rt)
{ if (end < lt || st > rt)
return range;
if (st >= lt && end <= rt)
return tr[node];
int mid = (st + end) / 2;
util1 lm = query(2 * node, st, mid, lt, rt);
util1 rm = query(2 * node + 1, mid + 1, end, lt, rt);
if (lm.bt1 < rm.bt1)
return lm;
return rm;
} // Function to perform non_preemptive // shortest job first and return the // completion time, turn around time and // waiting time for the given processes void non_preemptive_sjf( int n)
{ // To store the number of processes
// that have been completed
int counter = n;
// To keep an account of the number
// of processes that have been arrived
int upper_range = 0;
// Current running time
int tm = min(INT_MAX, ar[upper_range + 1].at);
// To find the list of processes whose arrival time
// is less than or equal to the current time
while (counter) {
for (; upper_range <= n;) {
upper_range++;
if (ar[upper_range].at > tm || upper_range > n) {
upper_range--;
break ;
}
update(1, 1, n, upper_range,
ar[upper_range].id, ar[upper_range].bt);
}
// To find the minimum of all the running times
// from the set of processes whose arrival time is
// less than or equal to the current time
util1 res = query(1, 1, n, 1, upper_range);
// Checking if the process has already been executed
if (res.bt1 != INT_MAX) {
counter--;
int index = mp[res.p_id];
tm += (res.bt1);
// Calculating and updating the array with
// the current time, turn around time and waiting time
ar[index].ct = tm ;
ar[index].tat = ar[index].ct - ar[index].at;
ar[index].wt = ar[index].tat - ar[index].bt;
// Update the process burst time with
// infinity when the process is executed
update(1, 1, n, index, INT_MAX, INT_MAX);
}
else {
tm = ar[upper_range + 1].at;
}
}
} // Function to call the functions and perform // shortest job first operation void execute( int n)
{ // Sort the array based on the arrival times
sort(ar + 1, ar + n + 1, cmp);
for ( int i = 1; i <= n; i++)
mp[ar[i].id] = i;
// Calling the function to perform
// non-preemptive-sjf
non_preemptive_sjf(n);
} // Function to print the required values after // performing shortest job first void print( int n)
{ cout << "ProcessId "
<< "Arrival Time "
<< "Burst Time "
<< "Completion Time "
<< "Turn Around Time "
<< "Waiting Time\n" ;
for ( int i = 1; i <= n; i++) {
cout << ar[i].id << " \t\t "
<< ar[i].at << " \t\t "
<< ar[i].bt << " \t\t "
<< ar[i].ct << " \t\t "
<< ar[i].tat << " \t\t "
<< ar[i].wt << " \n" ;
}
} // Driver code int main()
{ // Number of processes
int n = 5;
// Initializing the process id
// and burst time
range.p_id = INT_MAX;
range.bt1 = INT_MAX;
for ( int i = 1; i <= 4 * sh + 1; i++) {
tr[i].p_id = INT_MAX;
tr[i].bt1 = INT_MAX;
}
// Arrival time, Burst time and ID
// of the processes on which SJF needs
// to be performed
ar[1].at = 1;
ar[1].bt = 7;
ar[1].id = 1;
ar[2].at = 2;
ar[2].bt = 5;
ar[2].id = 2;
ar[3].at = 3;
ar[3].bt = 1;
ar[3].id = 3;
ar[4].at = 4;
ar[4].bt = 2;
ar[4].id = 4;
ar[5].at = 5;
ar[5].bt = 8;
ar[5].id = 5;
execute(n);
// Print the calculated time
print(n);
} |
// Java implementation of shortest job first // using the concept of segment tree import java.util.*;
class GFG {
static int z = 1000000007 ;
static int sh = 100000 ;
static class util {
// Process ID
int id;
// Arrival time
int at;
// Burst time
int bt;
// Completion time
int ct;
// Turnaround time
int tat;
// Waiting time
int wt;
}
// Array to store all the process information
// by implementing the above struct util
static util[] ar = new util[sh + 1 ];
static {
for ( int i = 0 ; i < sh + 1 ; i++) {
ar[i] = new util();
}
}
static class util1 {
// Process id
int p_id;
// burst time
int bt1;
};
static util1 range = new util1();
// Segment tree array to
// process the queries in nlogn
static util1[] tr = new util1[ 4 * sh + 5 ];
static {
for ( int i = 0 ; i < 4 * sh + 5 ; i++) {
tr[i] = new util1();
}
}
// To keep an account of where
// a particular process_id is
// in the segment tree base array
static int [] mp = new int [sh + 1 ];
// Comparator function to sort the
// struct array according to arrival time
// Function to update the burst time and process id
// in the segment tree
static void update( int node, int st, int end,
int ind, int id1, int b_t)
{
if (st == end) {
tr[node].p_id = id1;
tr[node].bt1 = b_t;
return ;
}
int mid = (st + end) / 2 ;
if (ind <= mid)
update( 2 * node, st, mid, ind, id1, b_t);
else
update( 2 * node + 1 , mid + 1 , end, ind, id1, b_t);
if (tr[ 2 * node].bt1 < tr[ 2 * node + 1 ].bt1) {
tr[node].bt1 = tr[ 2 * node].bt1;
tr[node].p_id = tr[ 2 * node].p_id;
} else {
tr[node].bt1 = tr[ 2 * node + 1 ].bt1;
tr[node].p_id = tr[ 2 * node + 1 ].p_id;
}
}
// Function to return the range minimum of the burst time
// of all the arrived processes using segment tree
static util1 query( int node, int st, int end,
int lt, int rt)
{
if (end < lt || st > rt)
return range;
if (st >= lt && end <= rt)
return tr[node];
int mid = (st + end) / 2 ;
util1 lm = query( 2 * node, st, mid, lt, rt);
util1 rm = query( 2 * node + 1 , mid + 1 , end, lt, rt);
if (lm.bt1 < rm.bt1)
return lm;
return rm;
}
// Function to perform non_preemptive
// shortest job first and return the
// completion time, turn around time and
// waiting time for the given processes
static void non_preemptive_sjf( int n) {
// To store the number of processes
// that have been completed
int counter = n;
// To keep an account of the number
// of processes that have been arrived
int upper_range = 0 ;
// Current running time
int tm = Math.min(Integer.MAX_VALUE, ar[upper_range + 1 ].at);
// To find the list of processes whose arrival time
// is less than or equal to the current time
while (counter != 0 ) {
for (; upper_range <= n;) {
upper_range++;
if (ar[upper_range].at > tm || upper_range > n) {
upper_range--;
break ;
}
update( 1 , 1 , n, upper_range, ar[upper_range].id,
ar[upper_range].bt);
}
// To find the minimum of all the running times
// from the set of processes whose arrival time is
// less than or equal to the current time
util1 res = query( 1 , 1 , n, 1 , upper_range);
// Checking if the process has already been executed
if (res.bt1 != Integer.MAX_VALUE) {
counter--;
int index = mp[res.p_id];
tm += (res.bt1);
// Calculating and updating the array with
// the current time, turn around time and waiting time
ar[index].ct = tm;
ar[index].tat = ar[index].ct - ar[index].at;
ar[index].wt = ar[index].tat - ar[index].bt;
// Update the process burst time with
// infinity when the process is executed
update( 1 , 1 , n, index, Integer.MAX_VALUE, Integer.MAX_VALUE);
} else {
tm = ar[upper_range + 1 ].at;
}
}
}
// Function to call the functions and perform
// shortest job first operation
static void execute( int n) {
// Sort the array based on the arrival times
Arrays.sort(ar, 1 , n, new Comparator<util>() {
public int compare(util a, util b) {
if (a.at == b.at)
return a.id - b.id;
return a.at - b.at;
}
});
for ( int i = 1 ; i <= n; i++)
mp[ar[i].id] = i;
// Calling the function to perform
// non-preemptive-sjf
non_preemptive_sjf(n);
}
// Function to print the required values after
// performing shortest job first
static void print( int n) {
System.out.println( "ProcessId Arrival Time Burst Time" +
" Completion Time Turn Around Time Waiting Time" );
for ( int i = 1 ; i <= n; i++) {
System.out.printf( "%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n" ,
ar[i].id, ar[i].at, ar[i].bt, ar[i].ct, ar[i].tat,
ar[i].wt);
}
}
// Driver Code
public static void main(String[] args)
{
// Number of processes
int n = 5 ;
// Initializing the process id
// and burst time
range.p_id = Integer.MAX_VALUE;
range.bt1 = Integer.MAX_VALUE;
for ( int i = 1 ; i <= 4 * sh + 1 ; i++)
{
tr[i].p_id = Integer.MAX_VALUE;
tr[i].bt1 = Integer.MAX_VALUE;
}
// Arrival time, Burst time and ID
// of the processes on which SJF needs
// to be performed
ar[ 1 ].at = 1 ;
ar[ 1 ].bt = 7 ;
ar[ 1 ].id = 1 ;
ar[ 2 ].at = 2 ;
ar[ 2 ].bt = 5 ;
ar[ 2 ].id = 2 ;
ar[ 3 ].at = 3 ;
ar[ 3 ].bt = 1 ;
ar[ 3 ].id = 3 ;
ar[ 4 ].at = 4 ;
ar[ 4 ].bt = 2 ;
ar[ 4 ].id = 4 ;
ar[ 5 ].at = 5 ;
ar[ 5 ].bt = 8 ;
ar[ 5 ].id = 5 ;
execute(n);
// Print the calculated time
print(n);
}
} // This code is contributed by // sanjeev2552 |
import sys
class Util:
def __init__( self ):
self . id = 0
self .at = 0
self .bt = 0
self .ct = 0
self .tat = 0
self .wt = 0
# Array to store all the process information by implementing the above Util class ar = [Util() for _ in range ( 100001 )]
class Util1:
def __init__( self ):
self .p_id = 0
self .bt1 = 0
# Segment tree array to process the queries in nlogn tr = [Util1() for _ in range ( 4 * 100001 + 5 )]
# To keep an account of where # a particular process_id is # in the segment tree base array mp = [ 0 ] * ( 100001 )
# Comparator function to sort the # struct array according to arrival time # Function to update the burst time and process id # in the segment tree def update(node, st, end, ind, id1, b_t):
if st = = end:
tr[node].p_id = id1
tr[node].bt1 = b_t
return
mid = (st + end) / / 2
if ind < = mid:
update( 2 * node, st, mid, ind, id1, b_t)
else :
update( 2 * node + 1 , mid + 1 , end, ind, id1, b_t)
if tr[ 2 * node].bt1 < tr[ 2 * node + 1 ].bt1:
tr[node].bt1 = tr[ 2 * node].bt1
tr[node].p_id = tr[ 2 * node].p_id
else :
tr[node].bt1 = tr[ 2 * node + 1 ].bt1
tr[node].p_id = tr[ 2 * node + 1 ].p_id
# Function to return the range minimum of the burst time # of all the arrived processes using segment tree def query(node, st, end, lt, rt):
range = Util1()
if end < lt or st > rt:
return range
if st > = lt and end < = rt:
return tr[node]
mid = (st + end) / / 2
lm = query( 2 * node, st, mid, lt, rt)
rm = query( 2 * node + 1 , mid + 1 , end, lt, rt)
if lm.bt1 < rm.bt1:
return lm
return rm
# Function to perform non_preemptive # shortest job first and return the # completion time, turn around time and # waiting time for the given processes def non_preemptive_sjf(n):
# To store the number of processes
# that have been completed
counter = n
# To keep an account of the number
# of processes that have been arrived
upper_range = 0
# Current running time
tm = min (sys.maxsize, ar[upper_range + 1 ].at)
# To find the list of processes whose arrival time
# is less than or equal to the current time
while counter ! = 0 :
for _ in range (upper_range + 1 ):
upper_range + = 1
if ar[upper_range].at > tm or upper_range > n:
upper_range - = 1
break
update( 1 , 1 , n, upper_range, ar[upper_range]. id , ar[upper_range].bt)
# To find the minimum of all the running times
# from the set of processes whose arrival time is
# less than or equal to the current time
res = query( 1 , 1 , n, 1 , upper_range)
# Checking if the process has already been executed
if res.bt1 ! = sys.maxsize:
counter - = 1
index = mp[res.p_id]
tm + = res.bt1
# Calculating and updating the array with
# the current time, turn around time and waiting time
ar[index].ct = tm
ar[index].tat = ar[index].ct - ar[index].at
ar[index].wt = ar[index].tat - ar[index].bt
# Update the process burst time with
# infinity when the process is executed
update( 1 , 1 , n, index, sys.maxsize, sys.maxsize)
else :
tm = ar[upper_range + 1 ].at
# Function to call the functions and perform # shortest job first operation def execute(n):
# Sort the array based on the arrival times
ar[ 1 :n + 1 ] = sorted (ar[ 1 :n + 1 ], key = lambda x: (x.at, x. id ))
for i in range ( 1 , n + 1 ):
mp[ar[i]. id ] = i
# Calling the function to perform non-preemptive-sjf
non_preemptive_sjf(n)
# Function to print the required values after # performing shortest job first def print_result(n):
print ( "ProcessId Arrival Time Burst Time" +
" Completion Time Turn Around Time Waiting Time" )
for i in range ( 1 , n + 1 ):
print (f "{ar[i].id}\t\t{ar[i].at}\t\t{ar[i].bt}\t\t{ar[i].ct}\t\t{ar[i].tat}\t\t{ar[i].wt}" )
# Driver Code if __name__ = = "__main__" :
# Number of processes
n = 5
# Initializing the process id
# and burst time
for i in range ( 1 , 4 * 100001 + 2 ):
tr[i].p_id = sys.maxsize
tr[i].bt1 = sys.maxsize
# Arrival time, Burst time and ID
# of the processes on which SJF needs
# to be performed
ar[ 1 ].at = 1
ar[ 1 ].bt = 7
ar[ 1 ]. id = 1
ar[ 2 ].at = 2
ar[ 2 ].bt = 5
ar[ 2 ]. id = 2
ar[ 3 ].at = 3
ar[ 3 ].bt = 1
ar[ 3 ]. id = 3
ar[ 4 ].at = 4
ar[ 4 ].bt = 2
ar[ 4 ]. id = 4
ar[ 5 ].at = 5
ar[ 5 ].bt = 8
ar[ 5 ]. id = 5
execute(n)
# Print the calculated time
print_result(n)
|
// C# implementation of shortest job first // using the concept of segment tree using System;
using System.Collections.Generic;
class util {
// Process ID
public int id;
// Arrival time
public int at;
// Burst time
public int bt;
// Completion time
public int ct;
// Turnaround time
public int tat;
// Waiting time
public int wt;
} class util1 {
// Process id
public int p_id;
// burst time
public int bt1;
}; class GFG {
static int sh = 100000;
// Array to store all the process information
// by implementing the above struct util
static util[] ar = new util[sh + 1];
static util1 range = new util1();
// Segment tree array to
// process the queries in nlogn
static util1[] tr = new util1[4 * sh + 5];
// To keep an account of where
// a particular process_id is
// in the segment tree base array
static int [] mp = new int [sh + 1];
// Comparator function to sort the
// struct array according to arrival time
// Function to update the burst time and process id
// in the segment tree
static void update( int node, int st, int end,
int ind, int id1, int b_t)
{
if (st == end) {
tr[node].p_id = id1;
tr[node].bt1 = b_t;
return ;
}
int mid = (st + end) / 2;
if (ind <= mid)
update(2 * node, st, mid, ind, id1, b_t);
else
update(2 * node + 1, mid + 1, end, ind, id1, b_t);
if (tr[2 * node].bt1 < tr[2 * node + 1].bt1) {
tr[node].bt1 = tr[2 * node].bt1;
tr[node].p_id = tr[2 * node].p_id;
} else {
tr[node].bt1 = tr[2 * node + 1].bt1;
tr[node].p_id = tr[2 * node + 1].p_id;
}
}
// Function to return the range minimum of the burst time
// of all the arrived processes using segment tree
static util1 query( int node, int st, int end,
int lt, int rt)
{
if (end < lt || st > rt)
return range;
if (st >= lt && end <= rt)
return tr[node];
int mid = (st + end) / 2;
util1 lm = query(2 * node, st, mid, lt, rt);
util1 rm = query(2 * node + 1, mid + 1, end, lt, rt);
if (lm.bt1 < rm.bt1)
return lm;
return rm;
}
// Function to perform non_preemptive
// shortest job first and return the
// completion time, turn around time and
// waiting time for the given processes
static void non_preemptive_sjf( int n) {
// To store the number of processes
// that have been completed
int counter = n;
// To keep an account of the number
// of processes that have been arrived
int upper_range = 0;
// Current running time
int tm = Math.Min(Int32.MaxValue, ar[upper_range + 1].at);
// To find the list of processes whose arrival time
// is less than or equal to the current time
while (counter != 0) {
for (; upper_range <= n;) {
upper_range++;
if (ar[upper_range].at > tm || upper_range > n) {
upper_range--;
break ;
}
update(1, 1, n, upper_range, ar[upper_range].id,
ar[upper_range].bt);
}
// To find the minimum of all the running times
// from the set of processes whose arrival time is
// less than or equal to the current time
util1 res = query(1, 1, n, 1, upper_range);
// Checking if the process has already been executed
if (res.bt1 != Int32.MaxValue) {
counter--;
int index = mp[res.p_id];
tm += (res.bt1);
// Calculating and updating the array with
// the current time, turn around time and waiting time
ar[index].ct = tm;
ar[index].tat = ar[index].ct - ar[index].at;
ar[index].wt = ar[index].tat - ar[index].bt;
// Update the process burst time with
// infinity when the process is executed
update(1, 1, n, index, Int32.MaxValue, Int32.MaxValue);
} else {
tm = ar[upper_range + 1].at;
}
}
}
// Function to call the functions and perform
// shortest job first operation
static void execute( int n) {
// Sort the array based on the arrival times
Array.Sort(ar, 1, n, Comparer<util>.Create( (a, b) => ( (a.at == b.at) ? (a.id - b.id) : (a.at - b.at))));
for ( int i = 1; i <= n; i++)
mp[ar[i].id] = i;
// Calling the function to perform
// non-preemptive-sjf
non_preemptive_sjf(n);
}
// Function to print the required values after
// performing shortest job first
static void print( int n) {
Console.WriteLine( "ProcessId Arrival Time Burst Time" +
" Completion Time Turn Around Time Waiting Time" );
for ( int i = 1; i <= n; i++) {
Console.Write(ar[i].id + "\t\t" + ar[i].at + "\t\t" + ar[i].bt + "\t\t" + ar[i].ct + "\t\t" + ar[i].tat + "\t\t" + ar[i].wt + "\n" );
}
}
// Driver Code
public static void Main( string [] args)
{
for ( int i = 0; i < sh + 1; i++) {
ar[i] = new util();
}
for ( int i = 0; i < 4 * sh + 5; i++)
tr[i] = new util1();
// Number of processes
int n = 5;
// Initializing the process id
// and burst time
range.p_id = Int32.MaxValue;
range.bt1 = Int32.MaxValue;
for ( int i = 1; i <= 4 * sh + 1; i++)
{
tr[i].p_id = Int32.MaxValue;
tr[i].bt1 = Int32.MaxValue;
}
// Arrival time, Burst time and ID
// of the processes on which SJF needs
// to be performed
ar[1].at = 1;
ar[1].bt = 7;
ar[1].id = 1;
ar[2].at = 2;
ar[2].bt = 5;
ar[2].id = 2;
ar[3].at = 3;
ar[3].bt = 1;
ar[3].id = 3;
ar[4].at = 4;
ar[4].bt = 2;
ar[4].id = 4;
ar[5].at = 5;
ar[5].bt = 8;
ar[5].id = 5;
execute(n);
// Print the calculated time
print(n);
}
} // This code is contributed by // phasing17 |
// JavaScript implementation of shortest job first // using the concept of segment tree class util { constructor() { // Process ID
this .id;
// Arrival time
this .at;
// Burst time
this .bt;
// Completion time
this .ct;
// Turnaround time
this .tat;
// Waiting time
this .wt;
} } class util1 { constructor()
{
// Process id
this .p_id;
// burst time
this .bt1;
}
}; let sh = 100000;
// Array to store all the process information
// by implementing the above struct util
let ar = new Array(sh + 1);
for ( var i = 0; i <= sh; i++)
ar[i] = new util();
let range = new util1();
// Segment tree array to
// process the queries in nlogn
let tr = new Array();
for ( var i = 0; i < 4 * sh + 5; i++)
tr.push( new util1());
// To keep an account of where
// a particular process_id is
// in the segment tree base array
let mp = new Array(sh + 1).fill(0);
// Comparator function to sort the
// struct array according to arrival time
// Function to update the burst time and process id
// in the segment tree
function update(node, st, end, ind, id1, b_t)
{
if (st == end) {
tr[node].p_id = id1;
tr[node].bt1 = b_t;
return ;
}
let mid = Math.floor((st + end) / 2);
if (ind <= mid)
update(2 * node, st, mid, ind, id1, b_t);
else
update(2 * node + 1, mid + 1, end, ind, id1, b_t);
if (tr[2 * node].bt1 < tr[2 * node + 1].bt1) {
tr[node].bt1 = tr[2 * node].bt1;
tr[node].p_id = tr[2 * node].p_id;
} else {
tr[node].bt1 = tr[2 * node + 1].bt1;
tr[node].p_id = tr[2 * node + 1].p_id;
}
}
// Function to return the range minimum of the burst time
// of all the arrived processes using segment tree
function query(node, st, end, lt, rt)
{
if (end < lt || st > rt)
return range;
if (st >= lt && end <= rt)
return tr[node];
let mid = (st + end) / 2;
let lm = query(2 * node, st, mid, lt, rt);
let rm = query(2 * node + 1, mid + 1, end, lt, rt);
if (lm.bt1 < rm.bt1)
return lm;
return rm;
}
// Function to perform non_preemptive
// shortest job first and return the
// completion time, turn around time and
// waiting time for the given processes
function non_preemptive_sjf( n) {
// To store the number of processes
// that have been completed
let counter = n;
// To keep an account of the number
// of processes that have been arrived
let upper_range = 0;
// Current running time
let tm = Math.min(Number.MAX_VALUE, ar[upper_range + 1].at);
// To find the list of processes whose arrival time
// is less than or equal to the current time
while (counter != 0) {
for (; upper_range <= n;) {
upper_range++;
if (ar[upper_range].at > tm || upper_range > n) {
upper_range--;
break ;
}
update(1, 1, n, upper_range, ar[upper_range].id,
ar[upper_range].bt);
}
// To find the minimum of all the running times
// from the set of processes whose arrival time is
// less than or equal to the current time
let res = query(1, 1, n, 1, upper_range);
// Checking if the process has already been executed
if (res.bt1 != Number.MAX_VALUE) {
counter--;
let index = mp[res.p_id];
tm += (res.bt1);
// Calculating and updating the array with
// the current time, turn around time and waiting time
ar[index].ct = tm;
ar[index].tat = ar[index].ct - ar[index].at;
ar[index].wt = ar[index].tat - ar[index].bt;
// Update the process burst time with
// infinity when the process is executed
update(1, 1, n, index, Number.MAX_VALUE, Number.MAX_VALUE);
} else {
tm = ar[upper_range + 1].at;
}
}
}
// Function to call the functions and perform
// shortest job first operation
function execute(n) {
// Sort the array based on the arrival times
ar.sort( function (a, b)
{ return ( (a.at == b.at) ? (a.id - b.id) : (a.at - b.at))});
for ( var i = 1; i <= n; i++)
mp[ar[i].id] = i;
// Calling the function to perform
// non-preemptive-sjf
non_preemptive_sjf(n);
}
// Function to print the required values after
// performing shortest job first
function print(n) {
console.log( "ProcessId Arrival Time Burst Time" +
" Completion Time Turn Around Time Waiting Time" );
for ( var i = 1; i <= n; i++) {
process.stdout.write(ar[i].id + "\t\t" + ar[i].at + "\t\t" + ar[i].bt + "\t\t" + ar[i].ct + "\t\t" + ar[i].tat + "\t\t" + ar[i].wt + "\n" );
}
}
// Driver Code
for ( var i = 0; i < sh + 1; i++) {
ar[i] = new util();
}
for ( var i = 0; i < 4 * sh + 5; i++)
tr[i] = new util1();
// Number of processes
var n = 5;
// Initializing the process id
// and burst time
range.p_id = Number.MAX_VALUE;
range.bt1 = Number.MAX_VALUE;
for ( var i = 1; i <= 4 * sh + 1; i++)
{
tr[i].p_id = Number.MAX_VALUE;
tr[i].bt1 = Number.MAX_VALUE;
}
// Arrival time, Burst time and ID
// of the processes on which SJF needs
// to be performed
ar[1].at = 1;
ar[1].bt = 7;
ar[1].id = 1;
ar[2].at = 2;
ar[2].bt = 5;
ar[2].id = 2;
ar[3].at = 3;
ar[3].bt = 1;
ar[3].id = 3;
ar[4].at = 4;
ar[4].bt = 2;
ar[4].id = 4;
ar[5].at = 5;
ar[5].bt = 8;
ar[5].id = 5;
execute(n);
// Print the calculated time
print(n);
// This code is contributed by // phasing17 |
ProcessId Arrival Time Burst Time Completion Time Turn Around Time Waiting Time 1 1 7 8 7 0 2 2 5 16 14 9 3 3 1 9 6 5 4 4 2 11 7 5 5 5 8 24 19 11
Time Complexity: In order to analyze the running time of the above algorithm, the following running times needs to be understood first:
- The time complexity to construct a segment tree for N processes is O(N).
- The time complexity to update a node in a segment tree is given by O(log(N)).
- The time complexity to perform a range minimum query in a segment tree is given by O(log(N)).
- Since the update operation and queries are performed for given N processes, the total time complexity of the algorithm is O(N*log(N)) where N is the number of processes.
- This algorithm performs better than the approach mentioned in this article because it takes O(N2) for execution.
Space Complexity: O(100000)