百度2016实习笔试:短作业优先调度算法(SJF)的平均等待时间

百度2016年春季实习生招聘的笔试题目的第二个编程题。笔试的时候没有通过所有的测试用例,结束后再Eclipse中编写通过。

短作业优先调度算法(SJF)

短作业优先调度算法(Short Job First)用于进程调度时又被称为短进程优先调度算法(Short Process First),该算法既可以用于作业调度,又可以用于进程调度。
在作业调度中,该算法每次从后备作业队列中挑选估计服务时间最短的一个或几个作业,将他们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中的原理类似。

问题例程

假设有n项作业位于就绪队列中,这些作业的提交时间用数组requestTimes按照提交时间的先后顺序存储,对应的作业服务时间(持续时间)用数组durations存储。采用SJF算法,计算n项作业的平均等待时间。当存在多个相同长度的短作业时,按照提交时间的先后顺序进行调度。假设0<= n <= 100。编码过程中限制使用java的某些类库。

public static float minWaitingTime(int[] requestTimes, int[] durations)

笔者注:

  • 服务时间:作业需要运行的时间
  • 完成时间 = 开始时间 + 服务时间
  • 等待时间 = 开始时间 - 提交时间
  • 周转时间 = 完成时间 - 提交时间
  • 带权周转时间 = 周转时间 / 服务时间
  • 响应比 = (等待时间 + 服务时间) / 服务时间 = 等待时间/服务时间 + 1

测试用例:
requestTimes = {0, 2, 4, 5};
durations = {7, 4, 1, 4};

作业名 提交时间 服务时间 开始时间 完成时间 等待时间 周转时间 带权周转时间
1 0 7 0 7 0 7 7/7
2 2 4 8 12 6 10 10/4
3 4 1 7 8 3 4 4/1
3 5 4 12 16 7 11 11/4

由上面的调度表可以知道,SJF算法的调度顺序为1->3->2->4;
平均等待时间:(0 + 6 + 3 + 7) / 4 = 4
平均周转时间和平均带权周转时间同理可以计算。

代码如下: 输出 4.0

/** * 百度实习: * * 最短作业优先算法的平均等待时间、平均周转时间 * * 等待时间 = 开始时间 - 提交时间,即响应时间 * 周转时间 = 完成时间 - 提交时间 * 完成时间 = 开始时间 + 服务时间 * * 注意:限制使用某些java类库 * * @author smile.lee * */
public class ShortJobFirst {

    public static void main(String[] args) {
        int[] requestTimes = {0, 2, 4, 5};
        int[] durations = {7, 4, 1, 4};

        float averageWaitingTime = ShortJobFirst.minWaitingTime(requestTimes, durations);
        System.out.println(averageWaitingTime);
    }

    /** * * @param requestTimes 任务提交时间 * @param durations 任务服务时间 * @return */
    public static float minWaitingTime(int[] requestTimes, int[] durations) {
        if(requestTimes == null || durations == null)
            return -1;
        if(requestTimes.length != durations.length)
            return -1;

        int n = requestTimes.length;
        int[] durationTimes = copyArray(durations); // 复制一份服务时间
        int[] startTimes = new int[n];  // 开始时间
        int[] endTime = new int[n]; // 结束时间
        int[] waitingTime = new int[n]; // 等待时间
        int[] cycleTime = new int[n];   // 周转时间

        // 第一个执行任务的开始时间、结束时间、等待时间
        startTimes[0] = requestTimes[0];
        endTime[0] = startTimes[0] + durations[0];
        waitingTime[0] = 0;

        /** 核心代码 **/
        int lastIndex = 0;  // 上一次执行任务的索引
        int minIndex = 0;   // 最短任务的索引
        for(int i = 1; i < n; i++) {
            minIndex = getMinIndex(durations);  // 作曲最短任务索引为当前任务
            startTimes[minIndex] = endTime[lastIndex];  // 当前任务的开始时间为上一个任务的结束时间
            endTime[minIndex] = startTimes[minIndex] + durationTimes[minIndex];  // 结束时间 = 开始时间 + 服务时间
            waitingTime[minIndex] = startTimes[minIndex] - requestTimes[minIndex];  // 等待时间 = 开始时间 - 提交时间
            cycleTime[minIndex] = endTime[minIndex] - requestTimes[minIndex];   // 周转时间 = 结束时间 - 提交时间
            lastIndex = minIndex; // 更新当前任务索引为下一次循环中的“上一次任务索引”
        }

        // 计算平均等待时间
        int s = 0;
        for(int i : waitingTime)
            s += i;
        float averageTime = (float) s / (float) n;
        return averageTime;
    }

    // 获取最短任务索引,获取完成之后,该任务的服务时间置为最大值,从下一次寻找最短任务的过程中排除。
    public static int getMinIndex(int[] arr) {
        if(arr == null)
            return -1;
        int minValue = Integer.MAX_VALUE;   // 最短任务值
        int minIndex = 0;
        for(int i = 1; i < arr.length; i++) {
            if(arr[i] < minValue) {
                minValue = arr[i];
                minIndex = i;
            }
        }

        arr[minIndex] = Integer.MAX_VALUE;  // 该任务的服务时间置为最大值,从下一次寻找最短任务的过程中排除。
        return minIndex;    // 返回索引
    }

    // 复制一份数组
    public static int[] copyArray(int[] arr) {
        if(arr == null)
            return null;
        int size = arr.length;
        int[] copyArr = new int[size];
        for(int i = 0; i < size; i++) {
            copyArr[i] = arr[i];
        }
        return copyArr;
    }
}

总结

代码实现该算法的核心在于调度切换时查找服务时间数组中的最小值,即最短作业,返回该值的数组索引,并将该处的数组值置为最大值,防止下一次查找最小值时产生干扰。由于查找过程中对输入的服务时间数据durations数组进行了更改,因此在调度前应当先保存一份该durations的副本,参与调度中的计算。

核心部分在于计算每一次调度的开始时间、完成时间,则可以计算出相应作业的等待时间、周转时间、带权周转时间。每一次调度的结果用数组保存,则相应的平均数很容易求出来。

你可能感兴趣的:(百度,短作业优先调度,平均等待时间,SJF)