Open In App

Shortest Job First (or SJF) CPU Scheduling Non-preemptive algorithm using Segment Tree

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. 
 

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: 
 

  1. 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.
  2. 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.
  3. 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 = Start Time + Burst Time
Turn Around Time = Completion Time – Arrival Time
Waiting Time = Turn Around Time – Burst Time
  1. 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

Output
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: 
 

 Space Complexity: O(100000)


Article Tags :