代码实现:
#include <iostream>
#include <stdio.h>
#include <malloc.h>
typedef struct node
{
char name;//进程名称
int arrive_time;//到达时间
int need_time;//需要的运行时间
int res_time;//剩余运行时间
int finished_time;//完成时间
int turn_time;//周转时间 = 完成时间 - 到达时间
int weight_turn_time;//带权周转时间 = 周转时间 /运行时间
char flag;//记录进程当前状态
struct node *next;
}PCB;
PCB* CreateList(int n)//创建进程队列
{
printf("开始创建进程啦:\n");//创建进程队列提示语句
PCB *head=(PCB*)malloc(sizeof(PCB));//分配存放头节点的指针
PCB *q=(PCB*)malloc(sizeof(PCB));//进程队列q
for(int i=0;i<n;i++)//n重循环输入n个进程的信息
{
PCB *pnew=(PCB*)malloc(sizeof(PCB));//用于存放当前进程的信息
if(i==0)//头节点指向第一个进程
head->next=pnew;
printf("请输入第%d个进程的名字,到达时间和服务时间\n",i+1);//物理位序和逻辑位序相差1
getchar();//吸收掉缓冲区可能存在的字符
scanf("%c%d%d",&pnew->name,&pnew->arrive_time,&pnew->need_time);//输入当前进程的相关信息
pnew->flag='R';//设置进程状态为未在运行
pnew->res_time=pnew->need_time;//初始化需要的剩余运行时间为运行时间
pnew->next=NULL;//置头节点的下一个为空指针域
//采用尾插法将该进程插入到 q之后
q->next=pnew;
q=pnew;
//getchar();
}
q->next=NULL;//尾节点的指针域置为 NULL;
q=NULL;
free(q);//释放掉q的空间,此时还有head指向该队列
return head;//返回头节点
}
void Push(PCB *p,PCB *t)//将新进程 t加入到 p队列中
{
PCB *q=p;
while(q->next)//使q指向队列的最后一个元素
{
q=q->next;
}
q->next=t;//将t接入到队列的最后一个元素之后,尾插法
t->next=NULL;//置最后一个节点的下一个指针域为 NULL
}
PCB* Pop(PCB *p)//弹出队首进程
{
PCB *top=(PCB*)malloc(sizeof(PCB));//为top指针申请内存空间
top=p->next;//top指向队首进程
p->next=p->next->next;//删除队首进程
top->next=NULL;//返回队首进程不影响队列其余元素,置top后继节点为空
return top;//返回队首进程
}
void sort(PCB *p,int n)//按照队列中进程的到达时间进行排序
{
PCB *r,*q;
bool exchange;//标记此趟比较是否有数进行了交换
//利用冒泡排序进行排序
for(int i=0;i<n;i++)
{
q=p;///q指向要排序的队列
exchange=false;
for(int j=0;j<n-i-1;j++)//冒泡排序每趟比较出一个最小值,所以每趟的比较次数递减
{
r=q->next;//r指向要比较的第二个数
//q指向要比较的第一个数
if(r->arrive_time<q->arrive_time)//若第一个数比第二个数大,则交换
{
q->next=r->next;//将q放在r之后
r->next=q;//将r放在q之前
exchange=true;
}
q=q->next;
}
if(!exchange) break;
}
}
void Run(PCB *p,int n,int piece)//运行进程
{
sort(p,n);//按照进程到达时间排序
PCB *cur=p;//当前运行进程
PCB *pool=p;//剩余未运行的进程队列
PCB *ready=(PCB *)malloc(sizeof(PCB));//就绪队列,含有头结点
ready->next=NULL;
int now_time=0;//当前时间
PCB *s;//用于打印进程队列的进程信息
//寻找第一个可执行进程
while(1)
{
//p队列的第一个是头节点
if(pool->next->arrive_time>now_time)//如果当前进程的到达时间大于当前时间,则表示当前进程不可执行
now_time++;//但由于该队列已排序,所以当前时间段内没有进程到达,now_time++;
else//找到了可运行的进程
{
PCB *temp=Pop(pool);
Push(ready,temp);//将进程池中的首进程弹出,放入就绪队列ready中
break;
}
}
while(1)
{
//寻找可以调度的进程
if(ready->next)//如果就绪队列不为空
{
cur=Pop(ready);//将就绪队列队首进程弹出并进入当前运行的进程队列
//打印正在运行的进程信息
printf("正在运行的进程如下:\n");
printf("进程名称 到达时间 服务时间 已运行时间 剩余运行时间\n");
printf("%c \t %d \t %d \t %d \t %d\n",cur->name,cur->arrive_time,cur->need_time,cur->need_time-cur->res_time,cur->res_time);
//进程运行
int slice=piece;//slice为时间片
while(cur->res_time&&slice)//当当前进程的还需运行时间大于0并且当前时间片大于0时,可以继续运行
{
slice--;//当前时间片减一
now_time++;//时间加一
cur->res_time--;//当前进程的还需运行时间减一
if(pool->next&&pool->next->arrive_time<=now_time)//当前时间变化,判断是否有可加入就绪队列的进程
{
PCB *temp=Pop(pool);
Push(ready,temp);//将进程池中的进程弹出并加入就绪队列
}
}
//打印当前就绪队列中的进程
printf("******************************************************此时的时间点为%d\n",now_time);
printf("进程%c执行一次后就绪队列中的进程如下:\n",cur->name);
printf("进程标识 到达时间 服务时间 已运行时间 还剩运行时间\n");
//检查当前进程是否运行结束
if(cur->res_time>0)//进程运行未结束
Push(ready,cur);//将该进程重新加入就绪队列队尾
else//进程运行结束,释放内存
{
cur->flag='C';//标记进程状态为C,已运行完成
PCB *temp=cur;
temp=NULL;
free(temp);//释放运行完的进程PCB的空间
cur=NULL; //置当前运行的进程为空
}
s=ready->next;
//输出就绪队列中尚未运行完的进程的信息
while(s)
{
if(s->flag=='R')
printf("%c \t %d \t %d \t %d \t %d\n",s->name,s->arrive_time,s->need_time,s->need_time-s->res_time,s->res_time);
s=s->next;
}
//判断是否所有进程都执行结束
if(pool->next==NULL&&ready->next==NULL){
printf("所有进程运行结束!!\n太棒啦!!!!!\n");break;
}
else{
printf("进程运行尚未完成,同志仍需努力!\n");
}
printf("\n");
}
else//就绪队列为空,进程池不为空
{
while(1)
{
if(pool->arrive_time>now_time)//若该进程不可运行
now_time++;
else//若该进程可以运行
{
PCB *temp=Pop(pool);
Push(ready,temp);//将该进程从进程池中弹出放入就绪队列中去。
break;//找到可运行进程,退出该循环
}
}
}
}
}
int main()
{
printf("\n请输入进程数目以及时间片(n m):");
int n;
int piece;
scanf("%d%d",&n,&piece);
PCB *p=CreateList(n);
Run(p,n,piece);
return 0;
}
/*
2 2
1 0 2
2 1 1
*/