数据结构银行排队系统实验报告
Assignment 1:ADT Applications
Task 2
133490***
实验过程:
在这个实验程序中,我认为,难点在于如何运用队列储存顾客等候情况、银行窗口如何设置实现显示当前顾客序号以及数据的统计和打印。
题目描述中,有两个模拟版本,分别是单队列与多队列。由于个人能力的原因,我选择实现程序的版本一。在类的设计上,我和舍友****进行了讨论,最后我的想法是设置两个类,分别是Customer 类与Bank 类。
其中Customer 类包括private 的数据如下:
private :
int ID;//顾客顺序号
int enterTime;//顾客进入时间 int startTime;//顾客开始被服务的时间 int serveTime;//(随机生成的)顾客服务时长
而Customer 类中包括的函数是public 的,包括以上所有数据的get 与set ,以及clear 函数。
程序的运行主要通过Bank 类来实现。public 的数据设置如下:
private :
int timeCounter;//计数循环次数,每次循环为一个时间单位 int totalWaitingTime;//被服务顾客的总等待时间 int totalServeNum;//被服务的顾客数 int totalNum;//总顾客数
int serveNum[5];//五个窗口各自处理的顾客数
vector serving;//存储当前五个窗口的顾客信息 vector wt;//被服务的顾客的等待时间集合 queue waiting;//等待队列
构造函数设置如下:
Bank() { }
timeCounter = 0; totalWaitingTime = 0; totalServeNum = 0; totalNum = 0; Customer c;
serving.assign(5, c);//每个窗口都初始化空的顾客 for (int i = 0; i
serveNum[i] = 0;
通过设置Bank 来得到程序的模拟结果。在利用五个窗口储存顾客信息的时候,原本想用的是数组形式,但数组进行插入和删除数据的时候很不方便,因此,利用了STL 中的vector ,并借助vector 的部分方法轻松完成把当前等待队伍的队头顾客pop 到第一个窗口的操作。
而对于每个窗口服务的顾客数,只要最简单的数组来存就可以了。另外,还设置了一个vector 来记录所有接受了服务的顾客的等待时间,方便最后数据的打印。
下面是Bank 类中函数的设计。
模拟主要通过成员函数work 调用其他成员函数来实现。
void work()
{
for (timeCounter = 0; timeCounter
if (timeCounter
Sleep(300);//每0.3秒进行一次实时信息打印
int n = rand() % randomLimit;//随机生成一定数量的顾客 for (int j = 0; j
Customer c;
totalNum++;//总顾客数+1
int t = rand() % timeLimit + 1;//顾客的服务时间随机生成 c.setServeTime(t); c.setID(totalNum);
c.setEnterTime(timeCounter); waiting.push(c);//顾客进入等待队列
接受新顾客
在实验中,一次循环就是一次时间单位。为了方便用户阅读模拟数据,因此设置每0.3秒挂起程序一次,从而实现每0.3秒刷新一次数据。其中调用的函数serve()与print()的作用分别是模拟窗口服务以及打印实时数据。而最后的statistic 则是打印最终的统计信息。具体内容如下。
void serve()
{
for (int i = 0; i
if (timeCounter >= serving[i].getStartTime() + serving[i].getServeTime())//说明第i 个窗口{
if (waiting.size() != 0)//若等待队列非空,则队列第一个用户到i 窗口 {
Customer c = waiting.front(); c.setStartTime(timeCounter);
是空的
}
else }
}
}
serving[i] = c; waiting.pop();
totalServeNum++;//总服务人数+1 serveNum[i]++;//第i 个窗口的服务人数+1
totalWaitingTime += timeCounter - c.getEnterTime();//计算总等待时间 wt.push_back(timeCounter - c.getEnterTime());//记录该用户的等待时间
serving[i].clear();//队列已空,队列中没有用户更新,因此需要把原来窗口中已经完成任
务的顾客移走
原本实时信息的打印采用的是清屏的方法,但这样不方便用户的浏览和信息的记录,因
此注释掉清屏,采用普通的连续打印信息。
void print()
{
//system("cls");
cout
cout
cout
for (int i = 0; i
cout
客已等待时间"
serving[i].getStartTime() - serving[i].getEnterTime()
cout
statistic 完成的是每个顾客得到服务之前等待时间单位数、被服务的顾客等待的平均时间
数、总顾客预计被服务的顾客的数量以及每个窗口处理的顾客数的统计数据的打印。
void statistic() { }
cout
cout
cout
cout
cout
endl;
该实验的流程图如下:
程序测试:
在实验中,我进行了多组参数的测试。根据打印的结果来看,统一信息都是正确合理的。但具体数据的设置对整个程序的模拟效果产生很大的影响,举例如下。
原先我并不知道运行的效果会怎么样,作为预实验,采用100个时间单位中第80个时间单位停止顾客进入等待队列,每个顾客的随机服务时间在1-5分钟内,每个时间单位随机生成0-5个顾客进入队列,最终的统计结果如下:
统计结果说明数据设置不合理,银行停止工作后仍有较多顾客没有被服务,平均等待时间太久。因此我进行了参数的更改。
第二次实验在60个时间单位时停止顾客的进入,其余参数不变,具体结果如下:
从统计结果来看,第95个时间单位时,队列已经空了,第96个时间单位开始,窗口位置有空缺。重复测试多次,平均在90个时间单位开始窗口出现空缺,这是一种浪费。因此数据仍需要修改。
另外,实际情况下,服务时间在1-5分钟内显得太短,因此将时间修改为1-15分钟的范围内,每个单位进入的顾客数在0-3范围内变动。但这组参数下到银行工作结束仍然有较多顾客在队列中等待服务,因此参数需要修改。得到的统计结果如下:
最后,我将单位时间进入银行的人数设置为0-2,在该模式下系统模拟结果较合理,时间在90左右队列中等待顾客减少到0,银行结束工作时,队列中剩余人数在0-4左右浮动,符合实际情况。
程序使用说明:
该程序使用十分方便,无需操作即可浏览相关信息。 对于参数设置为如下数据的程序,给出运行过程演示:
const int totalTime = 100;//总服务时间是100个时间单位
const int closeTime = 60;//到第
60
时间单位时不再接受顾客进入银行
const int timeLimit = 15;//每个顾客的随机服务时间范围是1-15分钟 const int randomLimit = 3;//每个时间单位随机进入的顾客数是0-2
欢迎界面,并显示程序参数。
运行过程中的数据。
程序结束。