题目:银行业务模拟
班级:计算机科学技术2004 姓名:张芳芳 学号: 031010151551005
一. 需求分析:
1.用 Visual C++ 工具设计实现一个用事件驱动的银行业务离散模型, 模拟每一个客户到达银行、排入人最少的业务窗口队列、排至窗口并处理完业务后离开的整个过程,统计客户在银行的平均逗留时间(即最近20人的平均逗留时间),适时地调整同时营业的窗口数(即能自动根据平均队长调整营业窗口数,缩减窗口时,应将此前排在被减窗口的客户继续处理完),在保持合理的逗留时间的条件下,节省银行投入的资源。假设相继到达银行的两乘客间的时间间隔(可用↑和↓来控制其大小)和每个客户业务处理花费时间长短都各不相同,而且应是随机的,其平均值可控制。
2.某时刻其状态的改变被称为”事件”,例如:一个客户到达银行;一个客户(处理完业务)从某窗口离开;一个客户排入某窗口的队尾;这些都是事件。按时间依次发生的事件序列就模拟了系统的运行。某些事件之间的因果关系表现为事件的驱动关系。针对模型的具体研究目标,需要对模型做一定简化,在能表现模型的主要性态的前提下,应设置尽可能少的事件。要求模拟两种事件:一个客户到达和一个客户从某窗口离开。要求形象地显示多个窗口队列的变化情况。
3.必须采用事件驱动的离散模型,不要采用时间驱动方案(指用计时器来确定事件发生的方式)。离散事件驱动模型的特点是只关注和刻画事 物的状态变化(即事件),不关心变化的过渡过程。这是对事物的一种简化,也会带来局限。模型靠每一个事件引发其它事件的方式来维持运转。每个事件都有发生时间,模型的运转实际就是按事件发生时间顺序逐个处理事件,'处理'将产生新的事件。因此,建模的关键就是全面分析事物的主要特点,抽象出几种能反映本质的事件和它们之间的驱动关系。有时,这种驱动关系不一定反映实际的因果关系,而是维持系统运转的需要。系统时间就是当前事件的事件发生时间,它不是等间隔变化而是跳跃变化的。
4.模型中的简化和假设应是合理的, 避免歪曲事物的主要性质。每个客户到达和下一客户到达时间的间隔以及每个客户业务花费时间都应是随机的,其平均值应便于调整。其中,客户到达时间的平均间隔应能在运行中用键盘实时调整。每个客户到达和下一个客户到达时间的间隔有时可能取零值(相当于两人同时到达),但每一个客户花费的业务处理时间则不可能取零值(>=1分钟)。
5.能比较形象地实时显示各队列的状态及客户平均逗留时间、平均队列长度、已办完业务的客户数。模型应能自动根据平均队长调整营业窗口数,缩减窗口时,应将此前排在被减窗口的客户继续处理完。
6.还要形象地实时显示系统时间,即当前业务发生时间,采用 分钟:秒 的形式输出,当到达银行关门时间时,若还有客户没处理完业务,将继续处理,直至最后一个客户离开,但不能延时过久,尽快将剩余客户处理完。
7.为了简化操作我没有用C语言而是用了C++,因为C++有地址传送,方便处理。 二. 概要设计:
1. 单链表的抽象数据类型定义为:
ADT eventlist{
数据对象:D={qi|qi∈ElemSet,i=1,2,……,n,n>=o} 数据关系:R={〈qi-1,qi>|qi-1,qi∈D,i=2,3,……,n} 队列的抽象数据类型定义: ADT Queue{
数据对象:D={ai|ai∈ElemSet,i=1,2,……,n,n>=o} 数据关系:R={〈ai-1,ai>|ai-1,ai∈D,i=2,3,……,n} 基本操作:
Initqueue(linkqueue &q)
操作结果:构造一个空的队列q;
Initlist(linklist &ev)
操作结果:构造一个空的链表ev;
Queueempty(linkqueue q) 初始条件:队列q已存在;
操作结果:若队列为空,则返回TURE,否则返回ERROR; Queuelength(linkqueue q) 初始条件:队列q已存在; 操作结果:返回队列的长度; Mininum(linkqueue q[])
初始条件:队列数组已存在
操作结果:返回队列数组中最短队的长度;
Enqueue(linkqueue &q,qelemtype e) 初始条件:队列数组已存在 操作结果:在队尾插入一个元素e Delqueue(linkqueue &q,int l) 初始条件:队列数组已存在 操作结果:删除队列q的队头
Orderinsert(eventlist &ev,event en) 初始条件:事件链表ev已存在
操作结果:将新生成客户到达事件插入事件链表ev中 Openforday()
操作结果:初始化操作 Customerarrived()
初始条件:初始化操作完毕 操作结果:处理客户到达事件 Customerdepature(event en)
初始条件:初始化操作完毕,已有客户到达 操作结果:处理客户离开事件 Time()
初始条件:客户到达时间已随机生成
操作结果:化为系统时间,用 分:秒 形式表示 Bank_Simulation()
初始条件:银行业务模拟
操作结果:打印出窗口,平均队长,近20人的平均逗留时间,客户到达人数
和已处理的客户人数
2.本程序包含五个模块: (1)主程序模块:
Void main(){ 接受命令; 处理命令; }
(2)事件链表表单元模块——实现链表的抽象数据类型; (3)队列单元模块——实现队列的抽象数据类型;
(4)事件结点结构单元模块——定义链表的结点结构; (5)队列结点结构单元模块——定义队列的结点结构;
各模块之间的调用关系如下:主程序模块—〉链表、队列表单元模块—>队列、链表结
点结构单元模块。
三. 详细设计: #define Qu 4 #define Khjg 5 #define Blsj 30 #include \"c1.h\" typedef struct {
int OccurTime; int NType; }Event,ElemType; #include \"c2_5.h\"
typedef LinkList EventList; #include \"bo2_5.cpp\"//
typedef struct {
int ArrivalTime; int Duration; }QElemType;
#include \"c3_2.h\" #include \"bo3_2.cpp\" //
EventList ev; Event en; Event et;
LinkQueue q[Qu]; QElemType customer;
int TotalTime=0,CustomerNum=0; int CloseTime;
int cmp(Event a, Event b) {
if(a.OccurTime==b.OccurTime) return 0; else
return(a.OccurTime-b.OccurTime)/abs(a.OccurTime-b.OccurTime); }
void OpenForDay() {
int i;
InitList(ev); en.OccurTime=0; en.NType=Qu;
OrderInsert(ev,en,cmp); for(i=0;i d=rand()%Blsj+1; i=rand()%Khjg+1; } int Minimum(LinkQueue Q[]) { int l[Qu]; int i,k; for(i=0;i for(i=1;i void CustomerArrived() { QElemType f; int durtime,intertime,i; ++CustomerNum; Random(durtime,intertime); et.OccurTime=en.OccurTime+intertime; et.NType=Qu; if(et.OccurTime if(QueueLength(q[i])==1) { et.OccurTime=en.OccurTime+durtime; et.NType=i; OrderInsert(ev,et,cmp); } } void CustomerDeparture() { int i; i=en.NType; DeQueue(q[i],customer); TotalTime+=en.OccurTime-customer.ArrivalTime; if(!QueueEmpty(q[i])) { GetHead(q[i],customer); et.OccurTime=en.OccurTime+customer.Duration; et.NType=i; OrderInsert(ev,et,cmp); } } void Bank_Simulation() { Link p; OpenForDay(); while(!ListEmpty(ev)) { DelFirst(ev,GetHead(ev),p); en.OccurTime=GetCurElem(p).OccurTime; en.NType=GetCurElem(p).NType; if(en.NType==Qu) CustomerArrived(); else CustomerDeparture(); } printf(\"客户总数:%d\\n客户共耗时:%d分钟\\n时:%d\\n\} int main() { printf(\"请输入银行营业时间(单位:分)\\n\"); scanf(\"%d\ Bank_Simulation(); return 0; } 四. 测试数据: 平均每人耗 五. 调试分析: 1.我在编写这些函数时觉得Orderinsert(eventlist &ev,event en)函数使我很迷惑,不知道该怎么插入新生事件,因为不是直接插入队尾,我不明白该用什么方法。后来又仔细研究了课本上那个例子才发现原来是比较事件发生时间,这样才正确插进去了。 2.显示队列时我遇到最大障碍,开始时每个队列只能显示一个客户,查了好久后发现原来我的事件表只生成了一个结点,而且后面的指针都没指正确,当然不对了,又做修改后发现又出了个大问题,队列只能进人却不能出人了,开始我怀疑是不是删除队头函数写错了,但查了很久发现并没错,又继续查,才发现原来在Customerdepature(event en)函数中,我没有写打印队列函数,这怎么能显示离开状态呢?修改后,显示就正常了。 3.开始我不知道老师要求的是近二十人的平均逗留时间,于是求的就是全部客户的平均逗留时间,后来老师说这样不行,还要修改,于是我又编写了一个数组专门来存放这二十人的,用这些人的全部逗留时间除以20才得到正确的时间。 4.我开始没有处理系统时间,即直接将随机生成的客户到达时间输出,在老师哪儿没有通过,经老师提点,原来分钟用ti/60显示,秒用ti%60显示即可。 5.在用上下键控制间隔时间时也有很多麻烦,发现编写算法后,虽然能调动时间的显示,但对队列的显示根本没有作用,又是一番周折才查出原来这两个地方根本没有联系起来,重新编写后,又调试好久才运行正常了。 七.附录 1.主程序:bank.cpp 2.常用定义文件:c1.h 3.链表定义与操作文件:c2_5.h bo2_5.h 4.队列定义与操作文件:c3-2.h bo3-2.h 因篇幅问题不能全部显示,请点此查看更多更全内容