您的位置:首页 > 编程语言 > Java开发

短进程优先算法(C,Java实现)

2017-10-26 17:03 155 查看
复制代码的时候:最好点下图 [cpp] 旁边的那个标签进行复制,不然可能代码编译不了。



在短进程优先算法中需要注意:下一个进程是已经到达且运行时间最短的进程。

输入如下:

4

A   8.00   2.00

B   8.50   0.50

C  9.00   0.10

D  9.50   0.20

输出如下:



C代码:

#include <stdio.h>
#include <stdlib.h>
#define INF 1000000.0

struct PCB {
char id[10];    // 进程ID
double reachTime;  // 进程到达的时间
double needTime;   // 进程完成需要的时间
double startTime;  // 进程开始的时刻
double finishTime; // 进程完成的时刻
double cTime;      // 进程周转时间
double wcTime;     // 进程带权周转时间
char state;       // 进程的状态( 设每个进程处于就绪R(ready),完成F(finish)两种状态之一 )
};

/* 两种情况:
1.在lastTime时刻,选择已经到达且拥有最短运行时间的进程
2.在lastTime时刻,没有进程到达,此时选择拥有最早到达时间的进程
*/
int findNext( struct PCB arr[], int length, double lastTime ) {
// p是已经到达且拥有最短运行时间的进程的下标
// q是没有到达的进程中拥有最早到达时间的进程的下标
int i, p, q;
double minNeedTime, minReachTime;
p = q = -1; minNeedTime = minReachTime = INF;
for( i = 0; i < length; i++ ) {
if( arr[i].state=='R' ) { // 进程处就绪状态
// 第一情况
if( arr[i].reachTime<=lastTime && arr[i].needTime<minNeedTime )
{ p = i; minNeedTime = arr[i].needTime; }
// 第二种情况
if( arr[i].reachTime>lastTime && arr[i].reachTime<minReachTime )
{ q = i; minReachTime = arr[i].reachTime; }
}
}
// p为-1时,代表在lastTime时刻还没进程到达,此时选择下一个最早到达的进程q
if( p != -1 ) return p;
return q;
}

int main() {
int num, i;
double lastTime;  // 为上一个进程的完成时间,用来确定当前进程的开始时间
struct PCB *arr;

printf( "请输入进程数:" );
scanf( "%d", &num );
arr = (struct PCB*)malloc(num*sizeof(struct PCB));

lastTime = INF;  // 最开始lastTime的为第一个作业的reachTime(到达时间)
printf( "请依次输入进程ID,进程到达时间,进程运行时间:\n" );
for( i = 0; i < num; i++ ) {
scanf( "%s%lf%lf", arr[i].id, &arr[i].reachTime, &arr[i].needTime );
arr[i].state = 'R';
if( lastTime>arr[i].reachTime ) lastTime = arr[i].reachTime;
}

// sum1为所有进程周转时间之和,sum2为所有进程带权周转时间之和
double sum1=0.0, sum2=0.0;
for( i = 0; i < num; i++ ) {
int p = findNext( arr, num, lastTime ); // 找到下一个将要执行的进程
// 两种情况:将要执行的进程可能已经到达,或者还没到达
if( arr[p].reachTime<=lastTime ) arr[p].startTime = lastTime;
else arr[p].startTime = arr[p].reachTime;
// 确定进程的完成时间,周转时间,带权周转时间
arr[p].finishTime = arr[p].startTime + arr[p].needTime;
arr[p].cTime = arr[p].finishTime - arr[p].reachTime;
arr[p].wcTime = arr[p].cTime/arr[p].needTime;
arr[p].state = 'F';

sum1 += arr[p].cTime;
sum2 += arr[p].wcTime;

lastTime = arr[p].finishTime; // 更新lastTime
}

printf( "\n进程  到达时间  运行时间  开始时间  完成时间  周转时间  带权周转时间\n" );
for( i = 0; i < num; i++ ) {
printf( "%4s  %8.2lf  %8.2lf  ", arr[i].id, arr[i].reachTime, arr[i].needTime );
printf( "%8.2lf  %8.2lf  ", arr[i].startTime, arr[i].finishTime );
printf( "%8.2lf  %12.2lf\n", arr[i].cTime, arr[i].wcTime );
}
printf( "平均周转时间: %.3lf\n", sum1/num );
printf( "平均带权周转时间: %.3lf\n", sum2/num );
return 0;
}


Java代码:

import java.util.Scanner;
import java.util.Arrays;

public class Main {
// 接口Comparable和类方法Arrays.sort()的配合使用可以使进程按reachTime(到达时间)排序
private static class PCB implements Comparable<PCB> {
String id;
float reachTime;
float needTime;
float startTime;
float finishTime;
char state;
public int compareTo( PCB b ) {
if( reachTime==b.reachTime ) return 0;
if( reachTime<b.reachTime ) return -1;
return 1;
}
}
private static final float INF = 10000000.0f;
/* 两种情况:
1.在lastTime时刻,选择已经到达且拥有最短运行时间的进程
2.在lastTime时刻,没有进程到达,此时选择拥有最早到达时间的进程
*/
private static int findNext( PCB[] arr, float lastTime ) {
int i, p = -1;
float minNeedTime = INF;
for( i = 0; i < arr.length; i++ ) {
if( arr[i].state=='R' ) {
/* 数组arr已经按reachTime排序,当出现
arr[i].reachTime>lastTime时,说明在lastTime时刻无进程到达,终止循环.*/
if( arr[i].reachTime > lastTime ) break;
if( arr[i].needTime < minNeedTime )
{ p = i; minNeedTime = arr[i].needTime; }
}
}
if( p != -1 ) return p;
return i;
}

public static void main( String[] args ) {
Scanner sc = new Scanner( System.in );

System.out.print( "请输入进程数:" );
int num = sc.nextInt();
PCB[] arr = new PCB[num];
System.out.println( "请依次输入进程ID,进程到达时间,进程运行时间:" );
for( int i = 0; i < num; i++ ) {
arr[i] = new PCB();
arr[i].id = sc.next();
arr[i].reachTime = sc.nextFloat();
arr[i].needTime = sc.nextFloat();
arr[i].state = 'R';
}
Arrays.sort(arr); // 使进程按reachTime(到达时间)排序

float lastTime=arr[0].reachTime;
for( int i=0; i<num; i++ ) {
// 找到下一个将要执行的进程
int p = findNext( arr, lastTime );
if( arr[p].reachTime<lastTime ) arr[p].startTime = lastTime;
else arr[p].startTime = arr[p].reachTime;
arr[p].finishTime = arr[p].startTime + arr[p].needTime;
arr[p].state = 'F';

lastTime = arr[p].finishTime;  // 更新lastTime
}

float sum1=0.0f, sum2=0.0f;
System.out.println( "\n进程  到达时间  运行时间  开始时间  完成时间  周转时间  带权周转时间" );
for( PCB jcb : arr ) {
System.out.format( "%4s  %8.2f  %8.2f  ", jcb.id, jcb.reachTime, jcb.needTime );
System.out.format( "%8.2f  %8.2f  ", jcb.startTime, jcb.finishTime );
System.out.format( "%8.2f  ", jcb.finishTime-jcb.reachTime );
System.out.format( "%12.2f\n", (jcb.finishTime-jcb.reachTime)/jcb.needTime );
sum1 += jcb.finishTime-jcb.reachTime;
sum2 += (jcb.finishTime-jcb.reachTime)/jcb.needTime;
}
System.out.format( "平均周转时间: %.3f\n", (sum1/num) );
System.out.format( "平均带权周转时间: %.3f", (sum2/num) );
}
}


如果你想实现以下效果:



可以将java代码的第 56- 66行代码换成以下代码:

/* 此时设每个进程处于就绪R(ready),运行E(excecuting),完成F(finish)三种状态之一,
并假设起始状态都是就绪状态 ) */
int p = 0, cnt = 0;
for( float time=arr[p].reachTime; cnt<num; time+=0.1 )
{
if( arr[p].reachTime<=time && arr[p].state=='R' )
{
arr[p].startTime = time;  // 记录开始时间
arr[p].state = 'E';
System.out.format( "在%.2f时刻: ", time );
System.out.format( "进程%s开始运行\n", arr[p].id );
}
else if( time-arr[p].startTime<arr[p].needTime && arr[p].state=='E' )
{
System.out.format( "在%.2f时刻: ", time );
System.out.format( "进程%s正在运行\n", arr[p].id );
}
else if( time-arr[p].startTime>=arr[p].needTime && arr[p].state=='E' )
{
arr[p].finishTime = time;  // 记录完成时间
arr[p].state = 'F';
System.out.format( "在%.2f时刻: ", time );
System.out.format( "进程%s完成运行\n\n", arr[p].id );

p = findNext( arr, time ); // 找到下一个要执行的进程
time -= 0.1;  // 这个很重要,用于结束时刻是否将有进程运行
cnt++;        // 已经完成cnt个进程
}
}


如果你要实现FCFS(先到先服务算法):

    将C的第61行代码换成 int p = i;     将Java代码的第59行代码也换成 int p = i;

即可实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息