数据结构实验二——队列(银行叫号系统)

一、实验目的

(1)掌握队列的链式存储结构

(2)掌握队列的基本操作,并能进行应用实践

(3)使用C/C++语言和队列实现”银行叫号系统“专题

二、实验任务

设计一个控制台程序,模拟银行排队业务,要求实现功能:

(1)输出程序界面,提示客户输入银行窗口数量和开放窗口时间

(2)客户随机时间进入银行,程序在事件表中记录客户进入时间和离开时间,并将客户排入窗口队列,办理完业务后退出队列

三、实验代码

1.事件链表

1.1 EventList.h

#pragma once
#include "pch.h"
#include "defineConst.h"
typedef struct Event 
{
	int time;//发生时刻
	int type;//事件类型:0表示顾客到达;1~N表示顾客从N号窗口离开
	struct Event *next;
}Event,*EventList;
int InitList(EventList &pList);  //初始化链表
int OrderInsert(EventList &pList, Event sEvent);   //按发生时刻的顺序向链表中插入元素
int isEmptyList(EventList pList);
int delFirst(EventList &pList, Event *pEvent);
int ListTravel(EventList pList);

1.2 EventList.cpp

#include "pch.h"
#include "EventList.h"
#include
#include
int InitList(EventList &pList)//初始化链表
{
	pList = (EventList)malloc(sizeof(Event));//开辟空间
	pList ->next= NULL;//下一个为空
	return OK;
}
int OrderInsert(EventList &pList, Event sEvent)//插入元素
{
	//临时变量,用于在链表中插入结点
	Event *pafter, *pbefore;
	pbefore = pList;
	pafter = pList->next;
	//比较事件发生的时间
	while (pafter != NULL && sEvent.time > pafter->time)
	{
		pbefore = pafter;
		pafter = pafter->next;
	}
	//创建一个新结点挂在Before和After两个结点之间
	pbefore->next = (Event *)malloc(sizeof(Event));
	//对新结点赋值
	pbefore->next->time = sEvent.time;
	pbefore->next->type = sEvent.type;
	pbefore->next->next = pafter;
	return OK;	
}

int isEmptyList(EventList pList)//判断链表是否为空
{
	if (pList->next ==NULL)
		return TRUE;
	else
		return FALSE;
}
int delFirst(EventList & pList, Event *pEvent)//删除首结点
{
	Event *ptmp;
	if (isEmptyList(pList))
	{
		printf("链表为空,无可删除节点");
		return ERROR;
	}
	else
	{
		//删除链表首结点
		ptmp = pList->next;
		pList->next = ptmp->next;
		*pEvent = *ptmp;//保存数值
		free(ptmp);//释放内存
		return OK;
	}
}
int ListTravel(EventList pList)//遍历链表
{
	Event *ptmp;
	ptmp = pList;
	while (ptmp->next != NULL)
	{
		ptmp = ptmp->next;
		if (ptmp->type == 0)
			printf("第%d分钟,下一名顾客即将到来。\n", ptmp->time);
		else
			printf("第%d分钟, %d号窗口顾客即将离开。\n", ptmp->time, ptmp->type);
	}
	printf("\n");
	return OK;
}

 

2.链式队列

2.1 LinkedQueue.h

#pragma once
#include "pch.h"
#include "defineConst.h"
typedef struct QElemType
{
	int time;
	int duration;
	struct QElemType *next;
}QElemType;
typedef struct LinkedQueue
{
	QElemType *front;//头指针
	QElemType *rear;//尾指针
}LinkedQueue;
int InitQueue(LinkedQueue *pQueue);
int isemptyQueue(LinkedQueue *pQueue);
int delFirstQueue(LinkedQueue *pQueue,QElemType *pQElem);
int enQueue(LinkedQueue *pQueue, QElemType sQElem);
int queueLength(LinkedQueue *pQueue);
int getHead(LinkedQueue *pQueue, QElemType * pQElem);
int queueTravel(LinkedQueue *pQueue);

2.2 LinkedQueue.cpp

#include "pch.h"
#include"LinkedQueue.h"
#include

int InitQueue(LinkedQueue *pQueue)
{
	//分配内存
	pQueue->front = pQueue->rear = (QElemType *)malloc(sizeof(QElemType));
	if (pQueue->front == NULL)
	{
		printf("分配内存失败!\n");
		exit(-1);
	}
	pQueue->front->next = NULL;
	return OK;
}
int isemptyQueue(LinkedQueue *pQueue)
{
	if (pQueue->front == pQueue->rear)
		return true;
	else
		return false;
}
int delFirstQueue(LinkedQueue *pQueue, QElemType *pQElem)
{
	QElemType *ptmp;//临时结点指针
	if (isemptyQueue(pQueue))
	{
		printf("队列为空,不能继续出队列\n");
		return ERROR;
	}
	else
	{
		ptmp = pQueue->front->next; //让ptmp指向队列的首节点的后一个元素
		*pQElem = *ptmp;    //将首节点的值复制给pQElem
		pQueue->front->next = ptmp->next;//front指针向后移动一位,删除这个结点
		if (pQueue->rear == ptmp)
		{
			pQueue->rear = pQueue->front;
		}
		free(ptmp);
		return OK;
	}
}
int enQueue(LinkedQueue *pQueue, QElemType sQElem)//结点入队操作
{
	QElemType *ptmp;//临时结点指针
	ptmp = (QElemType *)malloc(sizeof(QElemType));
	if (ptmp == NULL)
	{
		printf("分配内存失败!");
		exit(-1);
	}
	else
	{
		//尾节点指向新入队的元素
		*ptmp=sQElem;
		ptmp->next = NULL;
		pQueue->rear->next = ptmp;
		pQueue->rear = ptmp;
	}
	return OK;
}
int queueLength(LinkedQueue *pQueue)//获取队列长度
{
	QElemType *ptmp;//临时结点指针
	int count = 0;
	ptmp = pQueue->front->next;//队列第一个结点
	while (ptmp != NULL)
	{
		count++;
		ptmp = ptmp->next;
	}
	return count;
}
int getHead(LinkedQueue *pQueue, QElemType * pQElem)
{
	if (isemptyQueue(pQueue))
	{
		printf("队列为空!");
		return ERROR;
	}
	*pQElem = *(pQueue->front->next);
	return OK;
}
int queueTravel(LinkedQueue *pQueue)
{
	QElemType *ptmp;//临时结点指针
	if (isemptyQueue(pQueue))
	{
		printf("队列为空!\n");
		return ERROR;
	}
	ptmp = pQueue->front->next;//队列第一个结点
	while (ptmp != NULL)
	{
		printf("[到达时刻:第%d分钟,服务时长:%d分钟]\n",ptmp->time,ptmp->duration);
		ptmp = ptmp->next;
	}
	printf("\n");
	return OK;
}

 

3.主要业务功能

3.1 BankService.h

#pragma once
#include "pch.h"
#include "defineConst.h"
#include
void Initialize();
void CustomerArrived();
void CustomerLeaved();
int ShortestQueue();
void PrintQueue();
void PrintEventList();
void BankSimulation();

3.2 BankService.cpp

#include "pch.h"
#include "EventList.h"
#include "LinkedQueue.h"
#include"BankService.h"
#include
#include  
#include 
#define Maxsize 20//银行服务窗口最大数量
int gWindowNum;//银行服务窗口数
int gCustomerNum;//客户总人数
int gTotalTime;//总服务时间
int gCloseTime;//银行关闭时间
EventList gEventList;//事件列表
Event gEvent;//事件
LinkedQueue gQueue[Maxsize];//队列数组
QElemType gCustomer;//队列结点
void Initialize()//初始化数据
{
	int i;
	gTotalTime = 0;
	gCustomerNum = 0;
	InitList(gEventList);//初始化事件列表
	//服务窗口个数
	printf("请输入银行服务窗口个数(1~20):");
	scanf_s("%d", &gWindowNum);
	while (gWindowNum<1 || gWindowNum>Maxsize)
	{
		printf("请输入1到%d之间的整数:", Maxsize);
		scanf_s("%d", &gWindowNum);
	}
	//服务关闭时间
	printf("请输入服务关闭时间(超过这个时间就不再接纳新顾客)(单位:分钟):");
	scanf_s("%d", &gCloseTime);
	while (gCloseTime < 1)
	{
		printf("请输入大于零的整数:");
		scanf_s("%d", &gCloseTime);
	}
	//为每一个窗口建立一个空队列
	for (i = 0;i < gWindowNum;i++)
	{
		InitQueue(&gQueue[i]);
	}
}
void CustomerArrived()//处理客户到达事件
{
	QElemType sQElem;
	Event sEvent;
	int index;//排队人数最少的窗口编号
	int arrivetime;//客户到达时间
	int duration;//业务办理时间
	printf("当前时刻:第%d分钟\n", gEvent.time);
	//顾客到达的时间,在上一位顾客之后1~5分钟
	arrivetime = gEvent.time+ rand() % 5 + 1;
	duration = rand() % 21 + 10;//办理业务时间为10~30分钟
	if (arrivetime < gCloseTime)//服务尚未关闭
	{
		gCustomerNum++;
		//新顾客到达事件
		sEvent.time = arrivetime;
		sEvent.type = 0;
		OrderInsert(gEventList, sEvent);
		//顾客进入人数最少的窗口排队
		sQElem.time = gEvent.time;//入队时刻
		sQElem.duration = duration;//办理业务时间
		index = ShortestQueue();
		enQueue(&gQueue[index], sQElem);//入列
		//如果恰好排在了队首,预定离开事件
		if (queueLength(&gQueue[index]) == 1)
		{
			//记录顾客从第index+1号号窗口离开(因为索引从0开始)
			sEvent.time =gEvent.time + duration;
			sEvent.type = index + 1;
			OrderInsert(gEventList, sEvent);
		}
	}
	else//银行排队服务关闭,不再接受新客户
		printf("\n排队服务以关闭,不再接受新客户!\n");

}
void CustomerLeaved()//处理客户离开事件
{
	Event sEvent;
	int index = gEvent.type - 1;//队列编号为窗口编号-1
	delFirstQueue(&gQueue[index], &gCustomer);//删除队首节点
	printf("\n顾客离开时间:%d", gEvent.time);
	gTotalTime += gCustomer.duration;//记录服务时间
	//如果队列不为空,则预定下一位顾客从第index+1窗口离开
	if (isemptyQueue(&gQueue[index]))
	{
		getHead(&gQueue[index], &gCustomer);//获得下一位顾客
			// 记录离开事件
		sEvent.time = gEvent.time + gCustomer.duration;
		sEvent.type = index + 1;
		OrderInsert(gEventList, sEvent);
	}
}
int ShortestQueue()
{
	int i = 0;
	int min = 9999;//最短队列的长度
	int index = -1;//最短队列的编号
	int length = 0;
	//遍历各个窗口,比较哪个窗口排队的人数最少
	for (int i = 0;i < gWindowNum;i++)
	{
		length = queueLength(&gQueue[i]);
		if (min > length)
		{
			min = length;
			index=i;
		}
	}
	return index;
}
void PrintQueue()//显示当前窗口队列
{
	int i;
	printf("\n窗口排队状态:\n");
	for (i = 0;i < gWindowNum;i++)
	{
		printf("%d号窗口:\n",i+1);
		queueTravel(&gQueue[i]);
	}
	printf("\n");
}
void PrintEventList()//显示当前事件表
{
	printf("\n事件表状态:\n");
	ListTravel(gEventList);
}
void BankSimulation()//银行排队模拟
{
	//随机数发生器,用于模拟随机用户排队事件
	//根据当前系统时间初始化随机数种子
	srand((unsigned) time(NULL));
	//准备开业
	Initialize();
	//第一个顾客到来
	gEvent.time = 0;
	gEvent.type = 0;
	OrderInsert(gEventList, gEvent);
	//处理排队列表
	while (!isEmptyList(gEventList))
	{
		delFirst(gEventList, &gEvent);
		//处理顾客事件
		if (gEvent.type == 0)
			CustomerArrived();
		else
			CustomerLeaved();
		//显示当前事件列表,以及排队情况
		PrintEventList();
		PrintQueue();
		//暂停一会,便于观察输出内容
		system("PAUSE");
	}
	//平均服务时间
	printf("\n");
	printf("客服平均服务时间:%f分钟\n", (float)gTotalTime / gCustomerNum);
	system("PAUSE");
}

4.主函数

#include "pch.h"
#include"defineConst.h"
#include"BankService.h"
#include "EventList.h"
#include"LinkedQueue.h"
#include 

int main()
{
	BankSimulation();
}

5. 程序结果数据结构实验二——队列(银行叫号系统)_第1张图片数据结构实验二——队列(银行叫号系统)_第2张图片数据结构实验二——队列(银行叫号系统)_第3张图片

 

你可能感兴趣的:(数据结构)