银行业务模拟(2)银行业务模拟(难度系数4)[问题描述]客户业务分为两种。第一种是申请从银行得到一笔资金,即取款或借款。第二种是向银行投入一笔资金,即存款或换款。银行有两个服务窗口,相应地有两个队列。客户到达银行后先派第一个队列。处理每一个客户业务时,如属于第一种,且申请超出银行现存资金总额而得不到满足的,则立即排入第二个队列等候,直到满足时才离开银行;否则业务处理完后立即离开银行。每接待完一个第二种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的末尾。注意:在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待之前的数额,或者本次已将第二个队列检查或处理了一遍,就停止检查(因为此时已不可能还有满足者)转而继续接待第一个队列的客户。任何时刻都只开一个窗口。假设检查不需要时间。营业时间结束时所有客户立即离开银行。写一个上述银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。[基本要求]利用动态存储结构实现模拟。[测试数据]一天营业开始银行拥有的款项10000(元),营业时间为600分钟。其他模拟的参量自定。注意测定两种极端情况:一是两个到达事件之间的间隔很短,而客户的交易时间很长;另一个正好相反,设置两个到达事件的间隔时间很长,而客户之间交易的时间很短。[实现提示]事件有两类:到达银行和离开银行。初始时银行现存资金总额为Total。开始营业后的第一个事件是客户到达,营业时间从0到Closetime。到达事件发生时随机地设置各客户的交易时间和距下一次到达时间之间的时间间隔。每个客户要办理的款项也是随机确定的,用负值和正值分别表示第一类和第二类业务。变量Total、CloseTime以及上述两个随机量的上下界均交互地从终端读入,作为模拟参数。两个队列和一个事件表均要用动态的存储结构实现。注意弄清应该在什么条件下设置离开事件,以及第二个队列用怎样的存储结构实现可以获得较高的效率。注意:时间表是按照时间顺序有序的。#includeiostream#includestring#includetime.husingnamespacestd;inttotal;//初始时银行现存资金总额intcloseTime;//营业结束时间intarriveTime;//两个到达事件之间的间隔上限intdealTime;//客户之间交易的时间上限intdealMoney=5000;//交易额上限intcurrentTime=0;//当前时间inttotalTime=0;//客户逗留总时间intcounter=0;//客户总数intnumber=1;//初始客户序列号+structservice{intnum;//客户号stringtype;//到达或离开intbeginTime;intendTime;intmoney;//正数为存款,负数为取款service*next;};structqueue{//队列service*head;service*rear;};voidpush(queue&q,intd){//插入元素d为Q的新的队尾元素service*temp=newservice;temp-money=d;temp-next=NULL;if(NULL==q.head){//队列为空,初始化q.head=temp;q.rear=temp;}//ifelse{//队列不为空,插入元素dq.rear-next=temp;q.rear=q.rear-next;}//else}voidpop(queue&q){//若队列不空,出对列函数service*temp;temp=q.head;if(NULL==q.head-next)q.head=q.rear=NULL;elseq.head=q.head-next;deletetemp;}service*front(queue&q){//返回队首元素returnq.head;}service*back(queue&q){//返回队尾元素returnq.rear;}service*searchAndDel(queue&q,intm){//在对列中寻找可处理元素service*sign=q.head;//标记头节点service*temp;while(NULL!=q.head){if((-(q.head-money))m){//队首元素可以处理if(q.head==q.rear){temp=q.head;q.head=q.rear=NULL;returntemp;}//ifelse{//队首元素出列temp=q.head;q.head=q.head-next;//首节点后移一位,返回原首节点returntemp;}//else}//whileelse{//队首元首不能被处理if(q.head==q.rear){}else{//首节点移到队列尾部q.rear-next=q.head;q.rear=q.rear-next;q.head=q.head-next;q.rear-next=NULL;}//else}//elseif(q.head==sign)//队列循环一周时停止returnNULL;}returnNULL;}boolstate=1;//用于判断是否有窗口在处理intcurrentTimeOfDeal=0;inttheArriveTime=0;queueeq;//事件队列queuefq;//队列一queuesq;//对列二//初始化三个队列voidarrive(){/*到达函数随机产生顾客,进入队列一产生到达事件进入事件队列*/push(fq,(rand()%(2*dealMoney)-dealMoney));//随机产生顾客加入第一队列back(fq)-beginTime=currentTime;back(fq)-num=number;push(eq,(back(fq)-money));//将产生事件加入事件队列back(eq)-beginTime=currentTime;back(eq)-type=到达;back(eq)-num=number;++number;}voidputMoney(){//存款函数total+=front(fq)-money;//更新资金总额push(eq,front(fq)-money);//加入事件队列离开back(eq)-type=离开;back(eq)-num=front(fq)-num;back(eq)-endTime=(front(fq)-beginTime+rand()%dealTime+1);++counter;//更新客户总数totalTime+=(back(eq)-endTime-front(fq)-beginTime);//更新逗留时间pop(fq);//删除第一队列第一个业务currentTimeOfDeal=back(eq)-endTime;state=0;}voidgetMoney(){//取款函数if((-fq.head-money)total){//资金短缺加入第二队列push(sq,front(fq)-money);back(sq)-beginTime=front(fq)-beginTime;back(sq)-num=front(fq)-num;pop(fq);}//ifelse{total+=back(fq)-money;push(eq,front(fq)-money);//加入事件队列离开back(eq)-type=离开;back(eq)-num=front(fq)-num;back(eq)-endTime=(front(fq)-beginTime+rand()%dealTime+1);back(eq)-beginTime=0;currentTimeOfDeal=back(eq)-endTime;++counter;//更新客户总数totalTime+=(back(eq)-endTime-back(fq)-beginTime);//更新逗留时间pop(fq);//删除第一队列第一个业务state=0;}//else}service*temped;intrandomTemp;voidfindAndDeal(){//在对列中寻找可处理元素,对其进行处理while((temped=searchAndDel(sq,total))&&NULL!=temped){//查找可处理取款total+=temped-money;//更新资金总额push(eq,temped-money);//加入事件队列训离开back(eq)-type=离开;back(eq)-num=temped-num;randomTemp=rand()%dealTime+1;back(eq)-endTime=currentTime+randomTemp;currentTimeOfDeal+=randomTemp;++counter;//更新客户总数totalTime+=(back(eq)-endTime-temped-beginTime);//更新逗留时间deletetemped;//删除节点temped=NULL;}state=0;}intmain(){printf(********************************************\n);printf(欢迎进入银行模拟系统\n);printf(********************************************\n);printf(1.开始模拟0.退出\n);intn;scanf(%d,&n);while(n==1){srand(time(NULL));//初始化随机函数printf(输入银行的初始存款:\n);scanf(%d,&total);printf(输入银行的营业时间:\n);scanf(%d,&closeTime);printf(输入最大到达时间间隔:\n);scanf(%d,&arriveTime);printf(输入最大的处理时间:\n);scanf(%d,&dealTime);theArriveTime+=rand()%arriveTime+1;//首次到达时间while(currentTimecloseTime){++currentTime;if(currentTimeOfDealcurrentTime)currentTimeOfDeal=currentTime;if(currentTimeOfDeal==currentTime)state=1;if(currentTime==theArriveTime)//到达事件{arrive();theArriveTime+=rand()%arriveTime+1;}//ifif(1==state&&NULL!=fq.head){if(fq.head-money=0){putMoney();findAndDeal();}//ifelsegetMoney();}//if}coutendl客户序列\t事件类型\t\t时间\t处理金额endl;while(NULL!=eq.head)//清除事件队列{if(eq.head-type==离开)couteq.head-num\t\teq.head-type\t\t\t\teq.head-endTime\t\teq.head-moneyendl;if(eq.head-type==到达)couteq.head-num\t\teq.head-type\t\t\t\teq.head-beginTime\t\teq.head-mon