经典时间片轮转RR算法C语言实现

**RR算法主要体现在两个时机的调度:
1.进程的服务时间用完时,无论时间片到没到,时间片都需要置0。
2.进程的服务时间没用完,而且时间片到了,需要把此进程添加到队尾,时间片置0。
进程都运行结束时,调出循环的条件需要注意。
具体可以看注释:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;

typedef struct PCB 
{
	char name;
	int arrivaltime; //到达时间
	int Servicetime; //服务时间
	int Finishtime; //完成时间
	int Wholetime; //周转时间
	double WeightWholetime; //带权周转时间

}RR;
struct QueueNode { //链表结构
	RR node;
	struct QueueNode* next;
};

typedef struct {  //队列结构
	QueueNode* front; //队头
	QueueNode* rear;  //队尾
}LinkQueue;

void start_state(RR* ResultPCB,int n); //读入假设的数据,设置系统初始状态 
void dispath(LinkQueue* q_ready,RR* ResultPCB,int n);    // 模拟调度 
void frontNodeTorear(LinkQueue* q); //队首进程添到队尾
bool IsEmptyQueue(LinkQueue* q); //队列判空
void InitQueue(LinkQueue* q);    //分配内存
void InsertQueueNode(LinkQueue* q, RR TempPCB); //入队
bool DeleteQueueNode(LinkQueue* q); //出队
bool cmp(RR a,RR b); //排序辅助函数

int main()
{
	LinkQueue* q_ready = (LinkQueue*)malloc(sizeof(LinkQueue));   //为就绪队列分配内存空间
	InitQueue(q_ready);
	int n; //进程个数
	printf("Enter n:");
	scanf("%d", &n);
	
	RR* ResultPCB = (RR*)malloc(sizeof(RR)); //存储进程信息的结构体数组
	start_state(ResultPCB, n);   //进程初始化
	dispath(q_ready, ResultPCB, n); //调度


	//RR算法基本实现,下面进行数据汇总处理
	int SumWT = 0;
	double SumWWT = 0;
	printf("\nID\tArrivalTime\tServiceTime\tFinishTime\tWholeTime\tWeightWholeTime\n");
	for (int i = 0;i < n;i++) {
		ResultPCB[i].Wholetime = ResultPCB[i].Finishtime - ResultPCB[i].arrivaltime;
		ResultPCB[i].WeightWholetime = (1.0)*ResultPCB[i].Wholetime /ResultPCB[i].Servicetime;
		SumWT += ResultPCB[i].Wholetime;    //累计总周转时间
		SumWWT += ResultPCB[i].WeightWholetime; //累计总带权周转时间
		printf("%c\t\t%d\t\t%d\t\t%d\t\t%d\t\t%.2lf\n",ResultPCB[i].name, ResultPCB[i].arrivaltime, ResultPCB[i].Servicetime, ResultPCB[i].Finishtime, ResultPCB[i].Wholetime, ResultPCB[i].WeightWholetime);
	}
	double AverageWT = (1.0*SumWT) / n;   //平均周转时间
	double AverageWWT= (1.0 * SumWWT) / n;//平均带权周转时间
	printf("SumWT=%d\n", SumWT);
	printf("SumWWT=%.2lf\n", SumWWT);
	printf("AverageWT=%.2lf\n", AverageWT);
	printf("AverageWWT=%.2lf\n", AverageWWT);
	return 0;
}

void start_state(RR* ResultPCB, int n)  //初始化
{ 
	for (int i = 0;i < n;i++){
		ResultPCB[i].name = 'A' + i;
	}

	printf("Enter ArrivalTime:");
	for (int i = 0;i < n;i++) {
		scanf("%d", &ResultPCB[i].arrivaltime);
	}

	printf("Enter ServiceTime:");
	for (int i = 0;i < n;i++) {
		scanf("%d", &ResultPCB[i].Servicetime);
	}

	sort(ResultPCB, ResultPCB + n, cmp); //排序
}
void dispath(LinkQueue* q_ready, RR* ResultPCB, int n) //主要轮转算法实现
{
	int j = 0;  //累计入队的进程个数
	int SumoperateTime = 0; //总时间
	int x = 0; //累计时间片
	int t;     //时间片大小
	printf("Enter TimeSlice:");
	scanf("%d", &t);
	while(1)
	{
		if (j >= n && !q_ready->front->next) 
		{
			//当进入队列的进程个数为总进程数n时且队列为空时退出循环
			//表示所有进程全部运行结束
			break;  
		}
			
		printf("Time%d:", SumoperateTime); 
		for (int i = 0;i < n;i++)
		{
			if (ResultPCB[i].arrivaltime == SumoperateTime) 
			{//每次需要遍历所有进程到达时间,可能有些进程到达时间一样,依次入队
			
				printf(" %c arrived ", ResultPCB[i].name);
				InsertQueueNode(q_ready, ResultPCB[i]);   //添加新进程进入队列
				++j; //入队的进程个数
			}
		}
		

		if (0==q_ready->front->next->node.Servicetime) //队首进程服务时间用完时
		{
			printf(" %c finished.", q_ready->front->next->node.name); //finish表示此进程运行结束
			for (int i = 0;i < n;i++) {
				if (q_ready->front->next->node.name == ResultPCB[i].name) //遍历数组,找到与队首进程对应的项
				{
					ResultPCB[i].Finishtime = SumoperateTime;  //把总时间作为完成时间赋值给对应的进程
				}
			}
			DeleteQueueNode(q_ready); //注销队首进程
			x = 0;    //此时进程切换,时间片需要置0
		}
		else if (0<q_ready->front->next->node.Servicetime) //若队首进程还有服务时间
		{
			if (x < t) //如果不到时间片,则什么也不做,下次还是执行此队首进程
			{
				;
			}
			else  //如果到达时间片,此时需要进行进程切换
			{
				x = 0;  //无疑时间片需要置0
				if (!q_ready->front->next->next) //如果队里只有一个进程,没必要放到队尾
				{
					;
				}
				else   frontNodeTorear(q_ready); //如果有多个进程,则把队首进程移到队尾
			}
		}
		
		
		if (!IsEmptyQueue(q_ready)) //队列不空
		{
			printf(" %c executing.\n",q_ready->front->next->node.name); //执行队首进程
			--q_ready->front->next->node.Servicetime; //执行一次后服务时间减一
		}
		else  //队列为空
		{
			printf("***没有进程运行\n");
		}

		++x; //累计时间片
		++SumoperateTime; //累计总时间,用于明确各个进程完成时间
	}
	
}



void InitQueue(LinkQueue* q) { //初始化头结点
	q->front = q->rear = (QueueNode*)malloc(sizeof(QueueNode));
	q->front->next = NULL;
}

bool IsEmptyQueue(LinkQueue* q) { //判空
	if (q->front == q->rear)
		return true;
	return false;
}

void InsertQueueNode(LinkQueue* q, RR TempPCB) { //插入结点
	QueueNode* P = (QueueNode*)malloc(sizeof(QueueNode));
	P->node = TempPCB;
	P->next = NULL;
	q->rear->next = P;
	q->rear = P;
}

bool DeleteQueueNode(LinkQueue* q) {
	QueueNode* P = q->front->next;
	if (IsEmptyQueue(q))  //为空无法删除
		return false;
	q->front->next = P->next; //使头结点指向第一个结点的下一个结点
	if (P == q->rear)     //如果P是尾指针,直接使队头等于队尾
		q->rear = q->front;
	free(P);
	return true;
}

void frontNodeTorear(LinkQueue* q) {  //用作把队首结点移到队尾
	QueueNode* P = q->front->next;
	q->front->next = P->next;
	P->next = NULL;    //首进程摘下来
	q->rear->next = P; //尾部指针下一个指向摘下来的首进程
	q->rear = P;
}

bool cmp(RR a, RR b) //排序辅助函数
{
	return a.arrivaltime < b.arrivaltime;
}

运行实例如下:
时间片为4的情况:
在这里插入图片描述
时间片为1的情况:
在这里插入图片描述

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值