1. 程式人生 > >用C語言實現先來先服務FCFS程序排程演算法

用C語言實現先來先服務FCFS程序排程演算法

**分析:**先來先服務的意思就是哪個程序先到就先進行哪個程序,只與來的先後次序有關,等第一個程序執行完之後才會程序下一個程序的執行。

  1. 只有第一個程序的開始時間是它的到達時間,後邊的程序開始時間都是前一個進的完成時間。
  2. 完成時間就等於該程序的開始時間加上服務時間
  3. 週轉時間 = 完成時間 - 到達時間
  4. 帶權週轉時間 = 週轉時間 / 服務時間
    在這裡插入圖片描述

我們可以採用連結串列把這些程序資訊儲存起來,當第一個程序(結點)結束後,再進行下一個程序(結點)。我這裡採用的是頭插方法,結點插入完成後,最後一個程序是當前的頭結點,所以要進行連結串列反轉,將連結串列順序轉回來,這樣才能計算正確。

程式碼如下:
test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"os.h"

int main()
{
	_PCB* pcb;
	InitPcb(&pcb);//初始化函式
	printf("程序名\t到達時間\t服務時間\n");
	Input(&pcb);//插入結點
	OrderServer(_PCB** pcb);//核心演算法
	return 0;
}

os.c

void InitPcb(_PCB** pcb)
{
	assert(pcb);
	if (NULL == (*pcb))
		return;
	(*pcb) = NULL;
}

_PCB* BuyNode(_PCB* pcb)
{
	_PCB* newNode = (_PCB*)malloc(sizeof(_PCB));
	if (NULL == newNode)
		return NULL;
	else
	{
		setbuf(stdin, NULL);
		scanf("%c %d %d", &newNode->Name, &newNode->ArriveTime, &newNode->ServerTime);
		newNode->next = NULL;
		return newNode;
	}
}

void PushFront(_PCB** pcb)//頭插
{
	_PCB* cur = NULL;
	assert(pcb);
	if (*pcb == NULL)
	{
		(*pcb) = BuyNode(*pcb);
		return;
	}
	else
	{
		cur = BuyNode(*pcb);
		cur->next = (*pcb);
		(*pcb) = cur;
	}
}

void Input(_PCB** pcb)
{
	int i = 0;
	for (i = 0; i < MAX; i++)
	{
		PushFront(pcb);
	}
}

void Print(_PCB** pcb)
{
	_PCB* cur = NULL;
	cur = (*pcb);
	assert(pcb);
	if (NULL == (*pcb))
		return;
	printf("程序名\t到達時間\t服務時間\t開始執行時間\t完成時間\t週轉時間\t帶權週轉時間\n");
	while (cur)
	{
		printf("%c\t%d\t%d\t%d\t%d\t%d\t%f\n", cur->Name, cur->ArriveTime, cur->ServerTime, cur->StartTime, cur->FinishTime, cur->WholeTime, cur->ValueWholeTime);
		cur = cur->next;
	}
}

void Turn(_PCB** pcb)//反轉連結串列
{
	_PCB* cur = (*pcb);
	_PCB* pre = cur->next;
	_PCB* pb = pre->next;
	assert(pcb);
	if (NULL == pcb)
		return;
	cur->next = NULL;
	while (pre && pb)
	{
		pre->next = cur;
		cur = pre;
		pre = pb;
		pb = pb->next;
	}
	pre->next = cur;
	(*pcb) = pre;
}

void OrderServer(_PCB** pcb)
{
	_PCB* cur = NULL;
	_PCB* pre = NULL;//用來記錄前一個結點,計算開始執行時間需要用到前一個結點的資訊
	Turn(pcb);
	cur = pre = (*pcb);
	assert(pcb);
	int i = 0;//記錄當前是第幾個程序
	if (NULL == (*pcb))
		return;
	while (cur)
	{
		if (0 == i || 1 == i)//說明是第一個/第二個程序
		{
			if (0 == i)
			{
				cur->StartTime = cur->ArriveTime;
				i++;
			}
			else//是第二個程序,因為第二個程序的pre是頭結點,所以不需要移動,單獨出來
			{
				cur->StartTime = pre->FinishTime;
				i++;
			}
			cur->FinishTime = cur->ServerTime + cur->StartTime;
			cur->WholeTime = cur->FinishTime - cur->ArriveTime;
			cur->ValueWholeTime = (float)cur->WholeTime / (float)cur->ServerTime;
			cur = cur->next;
		}
		else
		{
			pre = pre->next;
			cur->StartTime = pre->FinishTime;
			cur->FinishTime = cur->ServerTime + cur->StartTime;
			cur->WholeTime = cur->FinishTime - cur->ArriveTime;
			cur->ValueWholeTime = (float)cur->WholeTime / (float)cur->ServerTime;
			cur = cur->next;
			i++;
		}
	}
}

os.h

#ifndef __OS_H__
#define __OS_H__
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define MAX 4

typedef struct PCB{
	char Name;//程序名
	int ArriveTime;//到達時間
	int ServerTime;//服務時間
	int Time;//時間片
	int Front;//優先順序
	int StartTime;//開始執行時間
	int FinishTime;//完成時間
	int WholeTime;//週轉時間
	float ValueWholeTime;//帶權週轉時間
	int Ago;//標記當前結點有沒有被訪問過
	struct PCB* next;
	int AddTime;//累加時間
	int AtTime;//當前時刻
}_PCB;

void InitPcb(_PCB** pcb);//初始化
_PCB* BuyNode(_PCB* pcb);
void PushFront(_PCB** pcb);//頭插
void Input(_PCB** pcb);//輸入函式
void Print(_PCB** pcb);//列印
void OrderServer(_PCB** pcb);//先來先服務
void Turn(_PCB** pcb);//將連結串列翻轉過來

執行結果:
在這裡插入圖片描述