模拟医院采血排队系统
(起评分85)某医院验血科室排队系统 假设某医院验血科室有两个采血窗口,其中1号窗口进行指尖采血工作,2号窗 口进行静脉采血工作。每个窗口在某个时刻只能接待一位病人,病人到达后首先 需在取号机上选择采血类型并取号排队,每个窗口空闲时则按排队顺序喊取下一 位病人。为更好利用资源提高采血效率,当某个窗口对应的待采血人数为0时系 统可以自动选择另一个窗口的病人到本窗口接收服务。请编制程序模拟医院的这 种活动,实时输出各窗口的排队情况,并在结束程序前输出所有病人的平均等待 时间。
要求:
(1)阐述算法使用的主要数据结构与实现的基本思路;
(2)给出具体编码与运行结果(包括代码和运行结果的截图);
(3)请分析算法时间复杂度和空间复杂度
阐述算法使用的主要数据结构与实现的基本思路
数据结构:
用了队列,将两种采血方式的排队用队列存储
对队的结构进行了优化,增加了记录队元素数量的length。
基本思路:
利用循环,循环一百次,代表明天最多采一百个人:
循环开始:
每次输入一个数,1代表选择了一种采血方式并加入Q1队列,2代表选择了另一种采血方方式并加入Q2队列,0为无人加入队列。利用reception()函数进行叫号。
在reception()里每次在两个队中各叫号一次,并实现当某个窗口对应的待采血人数为0时,系统可以自动选择另一个窗口的病人到本窗口接收服务的操作。
当输入0时无人加入队列,对剩下已经在排队的两个对进行叫号,也就是循环reception(),循环条件为(i <= Q1.length + Q2length)。
循环结束
给出具体编码与运行结果(包括代码和运行结果的截图)
主函数
int main()
{
Queue Q1,Q2;
InitQueue(Q1);
InitQueue(Q2);
InHere(Q1,1);
InHere(Q2,2);
int n,num = 0;
num = 10;
int i = 1;
while(i <= 100)
{
printf("请选择类型,输入数字1表示:指尖采血; 2:静脉采血; 0:表示没人加入队列\n");
scanf("%d",&n);
num++;
if(n == 1){
Push(Q1,num);
}
else if(n==2){
Push(Q2,num);
}
else if(n==0){
for(int j = 1;j<=Q1.length+Q2.length;j++)
{
reception(Q1,Q2);
}
}
reception(Q1,Q2);
i++;
}
return OK;
}
队列的初始化,入队,出队函数
int InitQueue(Queue &Q)//初始化
{
Q.base = (QElemtype*)malloc(QMAXSIZE*sizeof(QElemtype));
if(!Q.base) return ERROR;
Q.front = Q.rear = Q.length = 0;
return OK;
}
int Push(Queue &Q,int e)//排队(入队)
{
if((Q.rear+1)%QMAXSIZE == Q.front) return ERROR;
Q.base[Q.rear] = e;
Q.length++;
Q.rear = (Q.rear+1)%QMAXSIZE;
return OK;
}
int Pop(Queue &Q)//出队
{
if(Q.rear == Q.front) return ERROR;
printf("%d",Q.base[Q.front]);
Q.length--;
Q.front = (Q.front+1)%QMAXSIZE;
return OK;
}
在这里我假定在进行操作之前,已经有十个人排好队
void InHere(Queue &Q,int n)
{
for(int i = n;i <= 10;i = i+2)
{
Push(Q,i);
}
}
排队叫号函数
void reception(Queue &Q1,Queue &Q2)//叫号函数
{
if(Q1.length > 0&&Q2.length>0){
printf("请");Pop(Q1);printf("号到1号窗口\n");
printf("请");Pop(Q2);printf("号到2号窗口\n");
}
/*.....下面的两个当当某个窗口对应的待采血人数为0时系
统可以自动选择另一个窗口的病人到本窗口接收服务.......*/
else if(Q1.length>0&&Q2.length<=0){
printf("请");Pop(Q1);printf("号到1号窗口\n");
if(Q1.length>0){
printf("请");Pop(Q1);printf("号到2号窗口\n");
}
}
else if(Q1.length<=0&&Q2.length>0){
printf("请");Pop(Q2);printf("号到1号窗口\n");
if(Q2.length>0){
printf("请");Pop(Q2);printf("号到2号窗口\n");
}
}
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#define QMAXSIZE 20
#define ERROR 0
#define OK 1
typedef int QElemtype;
typedef struct
{
QElemtype *base;
int front;
int rear;
int length;
}Queue;
int InitQueue(Queue &Q);
int Push(Queue &Q,int e);
void InHere(Queue &Q,int n);
int Pop(Queue &Q);//出队
void reception(Queue &Q1,Queue &Q2);
int main()
{
Queue Q1,Q2;
InitQueue(Q1);
InitQueue(Q2);
InHere(Q1,1);
InHere(Q2,2);
int n,num = 0;
num = 10;
int i = 1;
while(i <= 100)
{
printf("请选择类型,输入数字1表示:指尖采血; 2:静脉采血; 0:表示没人加入队列\n");
scanf("%d",&n);
num++;
if(n == 1){
Push(Q1,num);
}
else if(n==2){
Push(Q2,num);
}
else if(n==0){
for(int j = 1;j<=Q1.length+Q2.length;j++)
{
reception(Q1,Q2);
}
}
reception(Q1,Q2);
i++;
}
return OK;
}
int InitQueue(Queue &Q)
{
Q.base = (QElemtype*)malloc(QMAXSIZE*sizeof(QElemtype));
if(!Q.base) return ERROR;
Q.front = Q.rear = Q.length = 0;
return OK;
}
int Push(Queue &Q,int e)//排队
{
if((Q.rear+1)%QMAXSIZE == Q.front) return ERROR;
Q.base[Q.rear] = e;
Q.length++;
Q.rear = (Q.rear+1)%QMAXSIZE;
return OK;
}
void InHere(Queue &Q,int n)
{
for(int i = n;i <= 10;i = i+2)
{
Push(Q,i);
}
}
int Pop(Queue &Q)//出队
{
if(Q.rear == Q.front) return ERROR;
printf("%d",Q.base[Q.front]);
Q.length--;
Q.front = (Q.front+1)%QMAXSIZE;
return OK;
}
void reception(Queue &Q1,Queue &Q2)//叫号函数
{
if(Q1.length > 0&&Q2.length>0){
printf("请");Pop(Q1);printf("号到1号窗口\n");
printf("请");Pop(Q2);printf("号到2号窗口\n");
}
/*下面的两个当当某个窗口对应的待采血人数为0时系
统可以自动选择另一个窗口的病人到本窗口接收服务*/
else if(Q1.length>0&&Q2.length<=0){
printf("请");Pop(Q1);printf("号到1号窗口\n");
if(Q1.length>0){
printf("请");Pop(Q1);printf("号到2号窗口\n");
}
}
else if(Q1.length<=0&&Q2.length>0){
printf("请");Pop(Q2);printf("号到1号窗口\n");
if(Q2.length>0){
printf("请");Pop(Q2);printf("号到2号窗口\n");
}
}
}
请分析算法时间复杂度和空间复杂度
时间复杂度:
代码中, 只要有人排队,每天会叫号叫到100个人,到100循环才会停止。
开始给队列给了20个连续的排队位置,所以在某个时间段最多每个队最多有20个人排队,共40个人。
从第一个人到第n个人的等待时间是一个等差数列,所以每个人的平均等待时间为
n/2 * (1+n)*1/n,即(n+1)/ 2。
空间复杂度:
数据结构为顺序存储表,开始自行初始化了一个连续的存储空间,也就是当可以预测每天的采血人员时,可以自行确定存储空间,比较灵活,用这个条件下,空间利用率会比较高。
而当没有自行确定初始存储空间时,会出现当人多时,空间利用率变高,但会出现大量的人无法排队;当人少时,可以排好队,但会出现大量的空间浪费。