数据结构_银行排队问题

题目如下:
在这里插入图片描述

代码:

#include <stdio.h>
#include <stdlib.h>
#define MaxWindow 3 		//定义最多有的窗口数 
#define MaxProc   60		//定义最长事务处理时间 

typedef struct People ElementType;
struct People				/*顾客类型*/
{	 
	int T;  				//顾客到达时间 
	int P;	   				// 顾客事务被处理时间 
};

typedef int Position;
struct QNode				/*队列节点*/ 
{		
	ElementType * Data;		//顾客数组
	Position  Front,Rear;	//队列的头、尾 指针 
	int MaxSize;			//队列的最大容量 
};
typedef struct QNode * Queue;

Queue CreateQueue(int MaxSize){			/*创建队列 Q 以及赋值*/ 
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->Data = (ElementType*)malloc(MaxSize*sizeof(ElementType));
	Q->Front = 0 ;
	Q->Rear = 0 ;
	Q->MaxSize = MaxSize ;
	return Q;
} 

bool IsFull(Queue Q){					/*判断队列 Q 是否为满*/ 
	return (Q->Rear+1) % Q->MaxSize == Q->Front ; 
}

bool AddQ( Queue Q , ElementType X ){	  /*将元素 X 压入队列*/
	if(!IsFull(Q)){
		Q->Rear = (Q->Rear+1) % Q->MaxSize ;
		Q->Data[Q->Rear] = X ;
		return true ; 
	}
}

bool IsEmpty(Queue Q){					/*判断队列 Q 是否为空*/ 
	return (Q->Front == Q->Rear);
}

ElementType DeleteQ(Queue Q){			/*队列出列*/ 
	if(!IsEmpty(Q)){
		Q->Front = (Q->Front+1) % Q->MaxSize ;
		return Q->Data[Q->Front] ;
	}
} 

int FindNextWindow(int W[],int K,int *WaitTime,int *Long)		/*给定 K个窗口,返回下一个空闲窗口的位置 以及在相邻两次窗口空闲之间所等待的时间 WaitTime 和窗口最长的事务处理时间*/
{	
	int WinAvail ; 						//下一个窗口的位置
	int MinW = MaxProc+1 ;				//最短事务处理时间,初始化为超过最大值
	int i ;
	int MaxTime=0; 
	
	for(i=0;i<K;i++)					//扫描每个窗口,找到最短事务处理时间 
		if(W[i] < MinW)
		{
			MinW = W[i];
			WinAvail = i;
		}
	*WaitTime = MinW ; 					//最短事务处理时间 就是两次空窗间的  等待时间
	
	for(int j=0;j<K;j++)				//扫描每个窗口,找到最长事务处理时间 
	{	if(W[j] > MaxTime)
			MaxTime = W[j];
	}
	*Long=MaxTime;						//最长的事务处理时间,用来求最后的完成时间 
	
	for( i=0; i<K ; i++ )				/*刷新所有窗口的事务处理状态*/ 
		W[i] -= MinW; 
	return WinAvail ; 					//返回下一个窗口的位置 
}

int FindMaxWaitTime(int A[],int N){		//用来寻找 MaxWaitTime[] 中最长的等待时间并返回 
	int MaxTime = 0;
	for(int i=0;i<N;i++)		
		if(A[i] > MaxTime)
			MaxTime = A[i];
	return MaxTime; 
} 


int FindLongTime(int Window[],int K,int CurrentTime)
{
	int LongTime = 0;
	for(int i=0;i<K;i++)
		if(Window[i] > LongTime)
			LongTime = Window[i];
	LongTime += CurrentTime;
	
	return LongTime;
} 


void QueueingAtBank(Queue Q,int N)		/*根据顾客队列 Q 和人数 N ,返回顾客的平均等待时间、最长等待时间、最后完成时间、各窗口服务的人数*/
{
	struct People Next;					//下一位顾客
	int K;								//营业窗口个数
	int i,j;
	
	
	/*---初始化----------------------------------------------*/ 
	int TotalTime=0;			//全体成员总的等待时间 /
	int CurrentTime=0;				//当前时间,开门营业时间为 0
	int Window[MaxWindow]={0};	//营业窗口需要处理事务的时间长度
	int WaitTime=0;					    //相邻两次窗口空闲之间所等待的时间
	int WinAvail=0;				//空闲时间窗口的位置
	
	int LongTime=0;				//最后完成时间 
	int Long=0;					//记录 FindNextWindow() K个窗口中最长处理事务时间
	
	int MaxN=0;					//顾客序号 
	int MaxWaitTime[N]={0};		//用来存放每个顾客的 最长等待时间 
	int Sum[MaxWindow]={0};				//用来统计每个窗口各服务了多少人 
	
	scanf("%d",&K);			    //读入营业窗口个数
	if(K>MaxWindow)				//当输入的窗口数大于规定的大窗口数时,按规定的最大的窗口数算 
		K=MaxWindow;
	while( !IsEmpty(Q) )
	{
	/*---第一步: 处理掉当前最短的事务,得到下一个空闲窗口*/
	WinAvail = FindNextWindow( Window , K , &WaitTime , &Long);		//用来寻找 WaiTime 和更新 CurrentTime 
	CurrentTime += WaitTime;	//当前时间=上一次处理完事务的当前时间+这次处理完事务的时间 
	
	/*---第二步:下一位顾客出列*/
	Next = DeleteQ(Q);
	if(CurrentTime >= Next.T)	//如果顾客已经到达等待 
	{		
		int G=TotalTime; 						//TotalTme = 在顾客 Q 前的全部顾客的等待时间 
		TotalTime += (CurrentTime-Next.T);		//TotalTime = 在顾客 Q 前的全部顾客的等待时间 + 当前顾客 Q 本身的等待时间 
		MaxWaitTime[MaxN] = TotalTime-G;		//所以 MaxWaitTime[MaxN] = 当前顾客 Q 本身的等待时间 
		MaxN++; 
	}
	else{ 					  //顾客不需要等待 
		WaitTime=Next.T-CurrentTime;  			//空闲窗口等待顾客的时间 
		for(j=0;j<K; j++){						//空闲窗口在等待顾客的同时其他窗口也在办理业务,所以需要重新刷新所有窗口至顾客到达的时间   ,此时当前时间就是顾客到达的时间		
			Window[j]-=WaitTime;
			if(Window[j]<0)
				Window[j]=0;
		}
		CurrentTime=Next.T;      				//更新当前时间为顾客到达时间 	 
	}
		
	/*----第三步:顾客 Next 到 WinAvail 窗口接受服务*/
	WinAvail = FindNextWindow( Window , K , &WaitTime , &Long);	//当上述 else 条件成立时,它会重新刷新所有窗口至顾客到达的时间,此时空闲窗口在等待顾客的同时其他窗口也在办理业务,所以存在一种可能,就是在第一次找到的窗口前面还会有空闲的窗口,所以需要重新刷新让其找到合适的位置 
	Sum[WinAvail]=Sum[WinAvail]+1;			//统计每个窗口的服务人数 
	if(Next.P>MaxProc)						//当顾客的事务处理时间 P 大于窗口的最长服务时间时,按窗口最长服务时间算 
		Next.P=MaxProc;
	Window[WinAvail]=Next.P;
    }
	
	WinAvail = FindNextWindow( Window , K , &WaitTime , &Long);	
	int Longtime=CurrentTime+Long; 
	
	printf("%.1lf %d %d\n",(double)TotalTime/(double)N,FindMaxWaitTime(MaxWaitTime,MaxN),Longtime);	//打印时间		
	for(int A=0;A<K;A++){ 	     		  //打印窗口服务顾客数且行末不能有空格 
 		if(A==K-1) 
		 	printf("%d",Sum[A]);
		else
			printf("%d ",Sum[A]);
	}
}

void DestroyQueue(Queue &Q)		/*销毁队列*/ 
{
   free(Q);
}

int main()	
{
	int N;		//顾客总数 
	Queue Q;	//顾客队列 
	int i;
	ElementType X;			//一个顾客结构体类型 
	scanf("%d",&N);			//读入顾客人数 
	Q=CreateQueue(N+1);		//建立空的顾客队列 
	for(i=0;i<N;i++){		//顾客依次入列 
		scanf("%d%d",&X.T,&X.P);
		AddQ(Q,X); 
	}
	QueueingAtBank(Q,N);	// 输出
	DestroyQueue(Q);	    //销毁队列 
	return 0;
}

/*
输入:
9
0 20
1 15
1 60 
2 10
10 5
10 3
30 18
31 25
31 2
3

注:
平均等待时间 = TotalTime 除以 顾客人数
最长等待时间 ,将各个顾客的等待时间存进一个数组 MaxWaitTime[] 中 , 调用函数  FindMaxWaitTime(int A[],int N) ,求出最长的等待时间 
最后完成时间 = 目前时间CurrenTime + 最大的顾客等待时间 
各个窗口服务人数 = 返回的WinAvail , 表示第 WinAvail 窗口这里来了一个顾客,用一个数组 Sum[] 来记录 							
*/ 
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AKA小徐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值