1. 先来先服务
    先来先服务(FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。FCFS算法简单易行,是一种非抢占式策略。
    2.短进程优先调度
    最短进程优先算法是一种非剥夺式算法,总是选取预计作业时间最短的作业优先运行;最短剩余时间优先算法是非剥夺式的,但可以改造成剥夺式的调度算法,称抢占式最短作业优先算法。
    至于二者的平均周转时间,比如有四个进程P1,P2,P3,P4,分别在0,1,2,3时刻到达,所需时间分别为7,5,3,8;那么其平均周转时间为((15-0)+(9-1)+(5-2)+(23-15))/4=8.5;
    公式:
    完成时间 = 开始时间 + 需要运行时间
    周转时间 = 完成时间 - 到达时间
    带权周转时间 = 周转时间 / 需要运行时间
    3.时间片轮转算法
    时间片轮转法(Round-Robin,RR)主要用于分时系统中的进程调度。为了实现轮转调度,系统把所有就绪进程按先入先出的原则排成一个队列。新来的进程加到就绪队列末尾。每当执行进程调度时,进程调度程序总是选出就绪队列的队首进程,让它在CPU上运行一个时间片的时间。时间片是一个小的时间单位,通常为10~100ms数量级。当进程用完分给它的时间片后,系统的计时器发出时钟中断,调度程序便停止该进程的运行,把它放入就绪队列的末尾;然后,把CPU分给就绪队列的队首进程,同样也让它运行一个时间片,如此往复。
    以下为上面三个算法的代码:(先来先服务和最短进程调度都为进程随机获得)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
//进程控制块(PCB)
struct PCB
{
 char name;
 int arrivetime;
 int servetime;
 int finishtime;
 float roundtime;
 float daiquantime;
 int sc;    //sign completion标志是否完成
 int st1;  //剩余服务时间
};
struct PCB a[50];
struct PCB b[50];
char *jczt[] = { "运行", "就绪" };//*表示没有字符串的大小限制
//打印统计信息
void tjxx(int n)
{
 float averoundtime = 0.0f;
 float avedaiquantime = 0.0f;
 printf("按任意键查看统计信息");
 getchar(); getchar();
 printf("\n\n进程名称\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间");
 for (int j = 0; j < n; j++)
 {
printf("\n %c\t\t%4d\t\t%4d\t\t%d\t\t%4.f\t\t %.2f\n", a[j].name, a[j].arrivetime, a[j].servetime, a[j].finishtime, a[j].roundtime, a[j].daiquantime);
   averoundtime += a[j].roundtime;
   avedaiquantime += a[j].daiquantime;
 }
 printf("\n平均周转时间:%.2f", averoundtime / n);
 printf("\n\n平均带权周转时间:%.2f\n", avedaiquantime / n);
}

//先来先服务
void fcfs(int n)
{
int time = 0; //定义当前时刻
int processnum = 0; //定义当前进程指向
struct PCB t; //定义一个空的结构体节点
int processztsy = 0; //定义进程状态索引
while (1)
{	printf("当前时刻:%2d\n", time);
	//排序
	for (int i = 1; i < n; i++)
	{ for (int j = 0; j < n - i; j++)
		{ if (a[j].arrivetime > a[j+1].arrivetime)//先到先运行
			{ t = a[j];
			  a[j] = a[j+1];
			  a[j+1] = t;
			}
			if (a[j].arrivetime == a[j + 1].arrivetime)//进程同时到
			{ if (a[j].servetime > a[j + 1].servetime)//比较服务时间,将运行时间短的放在优先级高的位置
				{ t = a[j];
				  a[j] = a[j + 1];
				  a[j + 1] = t;
				}
			}
		}
	}
	for (int k = 0; k< n; k++)
	{ if (time == a[k].arrivetime && a[k].arrivetime != 0)
		{ if (k >= 1 && time >= a[k - 1].finishtime || k == 0)
			processztsy = 0;
		  else
			processztsy = 1;
		  printf("\t\t进程 %c 到达\t进程状态\n", a[k].name);
		  printf("\n\t\t\t\t  %s\n\n", jczt[processztsy]);
		  if (processnum >= 1)
			{
				a[k].finishtime = a[k-1].finishtime + a[k].servetime;
				a[k].roundtime =(float)(a[k].finishtime - a[k].arrivetime);
				a[k].daiquantime = a[k].roundtime / a[k].servetime;
			}
			if (processnum == 0)
			{
				a[k].finishtime = a[k].arrivetime + a[k].servetime;
				a[k].roundtime =(float)(a[k].finishtime-a[k].arrivetime);
				a[k].daiquantime = a[k].roundtime / a[k].servetime;
				printf("\t\t\t进程  %c  开始\n\n", a[processnum].name);
				processnum++;
			}
		}
		if (time == a[k].finishtime && a[k].finishtime != 0)
		   printf("\t\t\t进程  %c  完成\n\n", a[k].name);
		if ((k >= 1 && time >= a[k].arrivetime && time == a[k - 1].finishtime && a[k].arrivetime != 0))
		   printf("\t\t\t进程  %c  开始\n\n", a[k].name);
	}
	if (time > a[n-1].finishtime && a[n-1].finishtime != 0)
	{
		printf("\t\t\t所有进程已进程已加载完毕!\n\n");
		break;
	}
	time++;
	Sleep(1000);
}
tjxx(n);
}

//短进程有先算法
void spf(int n)
{
struct PCB t;
int time = 0;//定义当前时刻
int jcnum = 0;
int jcztsy = 0;
bool ztgb = false;
//排序
for (int i = 1; i < n; i++)
{ for (int j = 0; j < n-i; j++)
	{ if (a[j].arrivetime > a[j+1].arrivetime)//先到达的优先级高
		{	t=a[j];
			a[j] = a[j+1];
			a[j+1] = t;
		}
	}
}
while (1)
{ printf("当前时刻:%d\n", time);
	//遍历数组,注意同时达到的进程,所以采用for循环遍历
  for (int k = 0; k< n; k++)
	{		//是否有进程的到达时间等于当前时刻
		if (time == a[k].arrivetime && a[k].arrivetime != 0)
		{	//判断到达进程因该处于什么状态
			if (k >= 1 && time >= a[k - 1].finishtime || k == 0)
			   jcztsy = 0;
			else
			   jcztsy = 1;
			printf("\t\t进程 %c 到达\t进程状态\n\n\n\n", a[k].name);
		}
	}
	if (jcnum == 0)
	{		//遍历数组
		for (int i = jcnum; i < n; i++)
		{	//把当前到达的进程筛选出来
			if (time >= a[i].arrivetime)
			{	//从挑选出来的进程中选取服务时间最短的一个
				if (a[i].servetime < a[jcnum].servetime)
				{ 	t = a[jcnum];
					a[jcnum] = a[i];
					a[i] = t;
				}
				ztgb = true;
			}
		}
		if (ztgb == true)
		{	printf("\t\t\t进程  %c  开始\n\n\n\n", a[jcnum].name);
			a[jcnum].finishtime = a[jcnum].arrivetime + a[jcnum].servetime;
			a[jcnum].roundtime =(float)(a[jcnum].finishtime - a[jcnum].arrivetime);
			a[jcnum].daiquantime = a[jcnum].roundtime / a[jcnum].servetime;
			ztgb = false;
			jcnum++;
		}
	}
	if (time == a[jcnum - 1].finishtime && a[jcnum - 1].finishtime != 0)
	{	printf("\t\t\t进程  %c  完成\n\n\n\n", a[jcnum - 1].name);
		//遍历数组
		for (int i = jcnum; i < n; i++)
		{	//把当前到达的进程筛选出来
			if (time >= a[i].arrivetime)
			{	//从挑选出来的进程中选取服务时间最短的一个
				if (a[i].servetime < a[jcnum].servetime)
				{	t = a[jcnum];
					a[jcnum] = a[i];
					a[i] = t;
				}
				ztgb = true;
			}
		}
		if (ztgb == true || jcnum == n-1)
		{
			printf("\t\t\t进程  %c  开始\n\n\n\n", a[jcnum].name);
			a[jcnum].finishtime = a[jcnum - 1].finishtime + a[jcnum].servetime;
			a[jcnum].roundtime =(float)(a[jcnum].finishtime - a[jcnum].arrivetime);
			a[jcnum].daiquantime = a[jcnum].roundtime / a[jcnum].servetime;
			ztgb = false;
			jcnum++;
		}
	}
	if (time > a[n - 1].finishtime && a[n - 1].finishtime != 0)
	{
		printf("\t\t\t所有进程已加载完毕! \n\n\n\n");
		break;
	}
	time++;
	Sleep(1000);
}
tjxx(n);
}

//时间片轮转算法
void rr(int n)
{        struct PCB t;
         int i,j,T;
         printf("\n请输入时间片:\n");
         scanf("%d",&T);
         for(i=0;i<n;i++)      //收集进程信息
         {
                   a[i].sc=0;
                   printf("\n%d:\n请依次输入进程的信息\n请输入进程名:",i+1);
                   scanf("%s",&a[i].name);
                   printf("请输入到达时间:");
                   scanf("%d",&a[i].arrivetime);
                   printf("请输入服务时间:");
                   scanf("%d",&a[i].servetime);
                   a[i].st1=a[i].servetime;
         }
 		 for(i=0;i<n;i++)
			 for(j=i+1;j<n;j++)   //按照各进程到达时间升序,对进程排序 注意:稳定的排序
			 {
                   if(a[j].arrivetime<a[i].arrivetime)
                   {
                           t=a[j];
                           a[j]=a[i];
                           a[i]=t;
                   }
			 }
         for(i=0;i<n;i++)
            printf("***排序后的***%12c%15d%11d%11d:\n",a[i].name,a[i].arrivetime,a[i].servetime,a[i].st1);
         int time1=a[0].arrivetime;      //当前时间的初值
         int flag=1;
         int sum=0;                                              //记录完成的进程数
		 int z=1;   //记录第几次调度进程
         printf("\n第几次调度进程 运行的进程名 开始运行时间 运行时间 剩余服务时间 结束时间\n");
         while(sum<n)
         {
          flag=0;           //标志就绪队列中是否还有进程
          for(i=0;i<n;i++)    //时间片轮转法执行各进程
          { if(a[i].sc==1)continue;  //已完成的进程
            else
			{  if(a[i].st1<=T && time1>=a[i].arrivetime)//未完成的进程但是还需服务的时间少于等于一个时间片
                 { flag=1;
                   time1=time1+a[i].st1;
                   a[i].sc=1;
                   a[i].finishtime=time1;
                   printf("%8d%12c%15d%11d%11d%11d\n",z++,a[i].name,time1-a[i].st1,a[i].st1,0,time1);
                   a[i].st1=0;
                  }
               else if( a[i].st1>T && time1>=a[i].arrivetime)//未完成的进程但其还需服务时间至少大于一个时间片
                  { flag=1;
                    time1=time1+T;
                    a[i].st1-=T;
                    printf("%8d%12c%15d%11d%11d%11d\n",z++,a[i].name,time1-T,T,a[i].st1,time1);
                   }
               if( a[i].sc==1)sum++;     //一个进程执行完就+1
            }
         }
         if(flag==0 && sum<n)   // 还有没执行的进程,且没进入就就绪队列
            for(i=0;i<n;i++)
			  if( a[i].sc==0) {  time1=a[ i].arrivetime;   break;}
    }
      for(i=0;i<n;i++)
	  { a[i].roundtime=(float)(a[i].finishtime - a[i].arrivetime);
	    a[i].daiquantime=a[i].roundtime / a[i].servetime;
	  }
	Sleep(1000);
	tjxx(n);
}

//信息输入
int info()
{ int n = 0;
  srand(time(NULL)); //初始化随机函数
  printf("请输入需要的进程数:");
  scanf("%d", &n);
  printf("\n");
  for (int i = 0; i < n; i++)
  { printf("进程 %d\t名称:", i+1);
    scanf("%s", &a[i].name);
    a[i].arrivetime = (rand() % 5 + 1);//随机获取进程运行到达时间
    a[i].servetime = (rand() % 5 + 1);//随机获取进程运行服务时间
  }
  system("cls");
  return n;
}

int info1()
{ int n;
  printf("请输入需要的进程数:");
  scanf("%d", &n);
  printf("\n");
  return n;
}

int main()
{
    int b=1,k,m;
    while(b)
    {
        system("cls");
        printf("*************************************************\n");
        printf("**                                             **\n");
        printf("**              进程调度算法                   **\n");
        printf("**              程序清单                       **\n");
        printf("**                                             **\n");
        printf("**              1.先来先服务算法               **\n");
        printf("**              2.短进程优先算法               **\n");
        printf("**              3.时间片轮转算法               **\n");
        printf("**              0.退出程序                     **\n");
        printf("**                                             **\n");
        printf("*************************************************\n");
        printf("请选择:");
        scanf("%d",&k);
        switch(k)
        {
            case 1:fcfs(info());break;
            case 2:spf(info());break;
            case 3:rr(info1()); break;
            case 0:b=0;break;
            default:printf("\n*****请输入正确的选择*****\n");
        }
        if(b!=0)
            printf("\n");
            system("pause");
    }
    printf("\n**********谢谢您使用**********\n");

}