1.需求分析
1.1输入的形式
输入的元素为整型类型;
输入的银行初始存款必须大于0;
输入的银行营业时间必须大于0且必须小于1440(一天);
输入的最大到达时间间隔必须大于0且必须小于银行营业时间;
输入的最小到达时间间隔必须大于0且必须小于最大到达时间间隔;
输入的最大处理时间必须大于0且必须小于银行营业时间;
输入的最小处理时间必须大于0且必须小于最大处理时间;
输入的交易额的最大上线必须大于0且必须小于银行初始存款且必须小于50000;
1.2输出的形式
输出的形式为以列表的形式输出事件处理序列;
并在列表输出完后输出需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。
1.3程序功能
实现银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。
1.4测试
测试数据由程序用户手动输入,此处对于正确输入和错误输入给出样例。
(1)错误的输入




(2)正确的输入

(3)对应的输出结果

2.概要设计
2.1数据类型
本设计中用到的数据结构ADT定义如下:

ADT Queue{数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n,  n≥0 }数据关系:R1={ <ai-1, ai>|ai-1, ai∈D, i=2,...,n }基本操作:
void InitQueue(Queue &Q);
操作结果:构造空队列Q
CustNode *Queuefront(Queue &Q);
初始条件:队列Q存在
操作结果:返回队首元素
CustNode *Queuerear(Queue &Q);
初始条件:队列Q存在
操作结果:返回队尾元素
void EnQueue(Queue &Q,int e);
初始条件:队列Q存在
操作结果:插入元素e为Q的新的队尾元素。
void DeQueue(Queue &Q);
初始条件:队列Q存在
操作结果:删除Q的队头元素。
}ADT Queue

2.2主程序的流程
主程序先是让外部进行测试数据输入,待测试数据输入完后,执行银行业务模拟系统,产生需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。

2.3程序模块说明

3.详细设计
3.1头文件声明
为了增强代码可读性,使用头文件来记录各类结构体的声明以及常用变量的定义

#ifndef _Bank_H_
#define _Bank_H_
#include <string>
using namespace std;/*客户结点类型*/
struct CustNode{                        int num;                            //客户号  string Type;                        //到达或离开  int BeginTime;                      //到达时间  int EndTime;                        //离开时间  int Amount;                         //正数为存款,负数为取款  CustNode *next;                 //指针域
};  Struct Client{
Int arrivertime;                    //到达时间
Int durtime;                        //逗留时间
Int amount;                     //办理业务金额
Client *next;                       //指针域
};
Client pool[MaxNumber];/*等待队列类型*/
struct Queue{                         CustNode *front;                    //队列头指针  CustNode *rear;                 //队列尾指针
}Queue;  /*常用变量定义*/
int BankAmount;                         //初始时银行现存资金总额
int CloseTime;                      //营业结束时间
int ClientArriveMaxTime;                //两个到达事件之间的间隔上限
int ClientArriveMinTime;                //两个到达事件之间的间隔下限
int DealMaxTime;                        //客户之间交易的时间上限
int DealMinTime;                        //客户之间交易的时间下限
int MaxAmount;                      //交易额上限
int NeedIn=0;                           //需要存款的人数
int NeedOut=0;                      //需要取款的人数
int SuccessIn=0;                        //成功存款的人数
int SuccessOut=0;                       //成功取款的人数
int CurrentTime=0;                  //当前时间
int BankAmountTime=0;               //客户逗留总时间
int counter=0;                      //客户总数
int number=1;                       //初始客户序列号
bool state=1;                           //用于判断是否有窗口在处理
int DealTime=0;                     //交易时间
int MaxTime=0;                      //最大到达时间
Queue Event;                            //事件队列
Queue Q1;                           //队列一
Queue Q2;                           //队列二
#endif
3.2选做算法
3.2.1动态分配函数
/*出栈,将栈顶元素的下标返回*/
伪码表示:
Begin
Client *p<-栈顶指针
e的arrivetime<-栈顶元素的arrivertime
e的durtime<-栈顶元素的durtime
e的amount<-栈顶元素的amount
栈顶指针指向下一元素
End
代码表示:
void myMalloc(Stack &S,Client &e){
Client *p=S.top;
e.arrivetime=(*S.top).arrivetime;
e.durtime=(*S.top).durtime;
e.amount=(*S.top).amount;
p->next=p->next->next;
S.top++;
p=p->next;
}
3.2.2归还函数
/*把该分量入栈*/
伪码表示:
Begin
Client *p<-栈顶指针
栈底元素的arrivertimee<-e的arrivetime
栈底元素的durtime<-e的durtime
栈底元素的amount<-e的amount
栈底指针指向下一元素
End
代码表示:
void myFree(Stack &S,Client e){
Client *p=S.rear;
(*S.rear).arrivertime=e.arrivetime;
(*S.rear).durtime=e.durtime;
(*S.rear).amount=e.amount;
p->next=p->next->next;
S.rear++;
p=p->next;
}
3.3函数算法
3.3.1创建队列
/*初始化操作,建立一个空队列*/
伪码表示:
Begin
分配存储空间给头结点和尾结点
IF头结点内存分配失败
EXIT
头结点的指针域<-空
End
代码表示:
void InitQueue(Queue &Q){  Q.front=Q.rear=(CustNode*)malloc(sizeof(CustNode));  if(!(Q.front))  exit(1);  Q.front->next=0;  }
3.3.2入队列
/*插入元素e为队列Q的新的队尾元素*/
伪码表示:
Begin
分配存储空间给结点p
结点p的金额置<-e
结点p的指针域<-空
IF队列<-空
Begin
头指针<-p
尾指针<-p
End
ELSE
Begin
头指针next域<-p
尾指针<-尾指针next域
End
End
代码表示:
void EnQueue(Queue &Q,int e){  CustNode* p=new CustNode;  p->Amount=e;  p->next=NULL; if(Q.front==NULL){      //队列为空,初始化    Q.front=p;  Q.rear=p;  }  else{                     //队列不为空,插入结点p    Q.rear->next=p;  Q.rear=Q.rear->next;  }
}
3.3.3出队列
/*使p中的第一个元素出队列*/
伪码表示:
Begin
p<-头指针
IF p的next域<-空
Begin
头指针<-空
尾指针<-空
End
ELSE
头指针<-头指针的next域
DELETE p
End
代码表示:
void DeQueue(Queue &Q){  CustNode *p;  p=Q.front;  if(Q.front->next==NULL)     //队列只有一个元素  Q.front=Q.rear=NULL;  else                        //调整队列头指针 Q.front=Q.front->next;  delete p;
}
3.3.4取队首
/*返回队首元素*/
伪码表示:
Begin
Return 队首元素
End
代码表示:
CustNode *Queuefront(Queue &Q){  return Q.front;
}3.3.5取队尾
/*返回队尾元素*/
伪码表示:
Begin
Return 队尾元素
End
代码表示:
CustNode *Queuerear(Queue &Q){  return Q.rear;
}
3.3.6处理客户到达事件
/*随机产生顾客,进入队列一产生到达事件 进入事件队列*/
伪码表示:
Begin
调用EnQueue(Q1,随机数)
Q1尾结点的BeginTime<-CurrentTime
Q1尾结点的num<-number
EnQueue(Event,尾结点的金额)
Event尾结点的BeginTime<-CurrentTime
Event尾结点的Type<-到达
Event尾结点的num<-number
number<-number+1
End
代码表示:
void ClientArrive(){  EnQueue(Q1,(rand()%(2*MaxAmount)-MaxAmount));   //随机产生顾客加入第一队列  Queuerear(Q1)->BeginTime=CurrentTime;               //当前时间为客户的到达时间  Queuerear(Q1)->num=number;                      //客户号为客户序列号  EnQueue(Event,(Queuerear(Q1)->Amount));             //将产生事件加入事件队列  Queuerear(Event)->BeginTime=CurrentTime;  Queuerear(Event)->Type="到达";  Queuerear(Event)->num=number;  number++;
}
3.3.7存款
/*对客户存款事件进行处理*/
伪码表示:
Begin
BankAmount<-BankAmount+Q1头结点的Amount
调用EnQueue(Event,Q1头结点的Amount)
Event尾结点的Type<-离开
Event尾结点的num<-Q1头结点的num
Event尾结点的EndTime<-Q1头结点的BeginTime+随机处理时间
counter<-counter+1
BankAmountTime<-BankAmountTime+Event尾结点的EndTime-Q1头结点的BeginTime
调用DeQueue(Q1)
DealTime<-Event尾结点的EndTime
state<-0
End
代码表示:
void InAmount(){BankAmount+=Queuefront(Q1)->Amount;             //更新资金总额  EnQueue(Event,Queuefront(Q1)->Amount);      //加入事件队列   Queuerear(Event)->Type="离开";  Queuerear(Event)->num=Queuefront(Q1)->num;  //离开时间为到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间 Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime+rand()%(DealMaxTime-DealMinTime +1)+DealMinTime);  counter++;                                  //更新客户总数
BankAmountTime+=(Queuerear(Event)->EndTime-Queuefront(Q1)->BeginTime);
//更新逗留时间  DeQueue(Q1);                                //删除第一队列第一个业务  DealTime=Queuerear(Event)->EndTime;         //交易时间为客户的离开时间  state=0;                                        //窗口没有交易需要处理
}
3.3.8取款或借款
/*对客户取款或借款事件进行处理*/
伪码表示:
Begin
IF -Q1头结点的Amount>BankAmount
Begin
调用EnQueue(Q2,Q1头结点的Amount)
Q2尾结点的BeginTime<-Q1头结点的BeginTime
Q2尾结点的num<-Q1头结点的num
调用DeQueue(Q1)
End
ELSE
Begin
BankAmount<-BankAmount+Q1尾结点的Amount
调用EnQueue(Event,Q1头结点的Amount)
Event尾结点的Type<-离开
Event尾结点的num<-Q1头结点的num
Event尾结点的EndTime<-Q1头结点的BeginTime+随机处理时间
DealTime<-Event尾结点的EndTime
counter<-counter+1
BankAmountTime<-Event尾结点的EndTime-Q1尾结点的BeginTime
调用DeQueue(Q1)
State<-0
End
End
代码表示:
void OutAmount(){   if((-Q1.front->Amount)>BankAmount){        //资金短缺 加入第二队列  EnQueue(Q2,Queuefront(Q1)->Amount);  Queuerear(Q2)->BeginTime=Queuefront(Q1)->BeginTime;  Queuerear(Q2)->num=Queuefront(Q1)->num;  DeQueue(Q1);  }  else{  BankAmount+=Queuerear(Q1)->Amount;          //更新资金总额  EnQueue(Event,Queuefront(Q1)->Amount);      //加入事件队列   Queuerear(Event)->Type="离开";  Queuerear(Event)->num=Queuefront(Q1)->num;  //客户的离开时间为客户的到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime +rand()%(DealMaxTime-DealMinTime +1)+DealMinTime);  Queuerear(Event)->BeginTime=0;  DealTime=Queuerear(Event)->EndTime;         //交易时间为客户的离开时间  counter++;                                  //更新客户总数   BankAmountTime+=(Queuerear(Event)->EndTime-Queuerear(Q1)->BeginTime);
//更新逗留时间  DeQueue(Q1);                                //删除第一队列第一个业务  state=0;                                        //窗口没有交易需要处理  }
}
3.3.9检查队列Q2
/*顺序检查队列Q2中是否有可以处理的事件元素*/
伪码表示:
Begin
sign<-Q头结点
CustNode *temp
While Q头结点为空
Begin
IF -Q头结点的Amount<m
Begin
IF Q为空
Begin
temp<-Q头结点
Q头结点<-空
Q尾结点<-空
Return temp
End
ELSE
Begin
temp<-Q头结点
Q头结点<-Q头结点的next域
Return temp
End
End
ELSE
Begin
IF Q不为空
Begin
Q尾结点的next域<-Q头结点
Q尾结点<-Q尾结点的next域
Q头结点<-Q头结点的next域
Q尾结点的next域<-空
End
End
IF Q头结点等于sign
Return 空
End
Return 空
End
代码表示:
CustNode *SearchQ2(Queue &Q,int m){   CustNode *sign=Q.front;                 //标记头节点  CustNode *temp;  while(Q.front!=NULL){  if((-(Q.front->Amount))<m){         //队首元素可以处理  if(Q.front==Q.rear){  temp=Q.front;  Q.front=Q.rear=NULL;  return temp;  }  else{                           //队首元素出列  temp=Q.front;   Q.front=Q.front->next;      // 首节点后移一位,返回原首节点  return temp;  }  }  else{                               //队首元首不能被处理  if(Q.front==Q.rear){}  else{                           //首节点移到队列尾部  Q.rear->next=Q.front;   Q.rear=Q.rear->next;  Q.front=Q.front->next;  Q.rear->next=NULL;  }  }  if(Q.front==sign)                   //队列循环一周时停止  return NULL;  }  return NULL;
}
3.3.10处理队列Q2
/*对于队列Q2中可以处理的事件元素进行处理*/
伪码表示:
Begin
CustNode* temped  int RandomTemp
While temped<-调用SearchQ2(Q2,BankAmount)并且temped不为空
Begin
BankAmount<-temped的Amount+BankAmount
EnQueue(Event,temped的Amount
Event尾结点的Type<-离开
Event尾结点的num<-temped的num
RandomTemp<-随机处理时间
Event尾结点的EndTime<-CurrentTime+RandomTemp
DealTime<-DealTime+RandomTemp
counter<-counter+1
BankAmountTime<-Event尾结点的EndTime-temped的BeginTime+BankAmount
删除 temped
temped<-空
End
state<-0
End代码表示:
void DealQ2(){ CustNode* temped;  int randomTemp;while((temped=SearchQ2(Q2,BankAmount))&&temped!=NULL){  //查找可处理取款  BankAmount+=temped->Amount;                         //更新资金总额  EnQueue(Event,temped->Amount);                      //加入事件队列   Queuerear(Event)->Type="离开";  Queuerear(Event)->num=temped->num;  RandomTemp=rand()%(DealMaxTime-DealMinTime +1)+DealMinTime;
//处理时间为随机产生的介于最大处理时间和最小处理时间之间的处理时间  Queuerear(Event)->EndTime=CurrentTime+randomTemp ;
//客户离开时间为当前时间加上处理时间  DealTime+=randomTemp;                               //更新交易时间  counter++;                                          //更新客户总数  BankAmountTime+=(Queuerear(Event)->EndTime-temped->BeginTime);
//更新逗留时间   delete temped;                                      //删除节点  temped = NULL;  }  state = 0;
}
3.3.11银行业务模拟系统界面
/*银行业务模拟程序的界面*/
伪码表示:
Begin
输出   =========================================================================      换行
输出   =========================================================================      换行
输出                      Simulation of The Bank business
换行
输出                  -------------------------------------------------------------------------
换行
输出                             ---------------------------------
换行
输出                                  Number: 3116004979
输出                               CLASS :16网络二班
输出                                   NAME  : 詹泽霖
输出   =========================================================================      换行
输出  *************************************************************************
换行  输出   *************************************************************************      换行  输出   *******************                               ***********************      换行输出   *******************    0.退出   1.进入模拟系统    ***********************
换行   输出   *******************                               ***********************      换行 输出  *************************************************************************
换行   输出  *************************************************************************
换行  输出   ************************      请选择服务      ***************************       换行
输出   =========================================================================      换行End
代码表示:
void BankOutLook(){       printf("   =========================================================================        \n");
printf("   =========================================================================        \n");printf("                        Simulation of The Bank business                         \n");printf("            -------------------------------------------------------------------------                       \n\n");printf("                              ---------------------------------                                     \n");printf("                                  Number: 3116004979                                        \n");printf("                                 CLASS :16网络二班                                          \n");printf("                                  NAME  :  詹泽霖                                              \n");printf("                              ---------------------------------                                         \n");printf("   =========================================================================        \n");printf("   *************************************************************************                            \n");  printf("   *************************************************************************                            \n");  printf("   *******************                               **************                         \n");printf("   *******************    0.退出   1.进入模拟系统    ***************                            \n");   printf("   *******************                               **************                         \n"); printf("   *************************************************************************                            \n");  printf("   *************************************************************************                            \n");  printf("   ************************      请选择服务      *********************                           \n");printf(" =========================================================================          \n");printf("   请输入选择的操作对应编号:");
}
3.4主程序
通过对以上定义过的函数接口的调用,利用主函数来构建一个银行模拟系统,以列表的形式输出事件处理序列;
并在列表输出完后输出需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。
3.4.1伪码表示
Begin
调整界面为黑字白背景
调用BankOutLook()
输入操作编号
While 操作编号等于1
Begin
初始化随机函数
输出 请输入银行的初始存款
输入 银行初始存款
IF 银行初始存款<0
Begin
输出 输入错误,重新输入
输入 银行初始存款
IF 银行初始存款<0
Begin
输出 输入错误,重新输入
输入 银行初始存款
IF银行初始存款<0
输出 三次输入错误,退出
End
End输出 请输入银行的营业时间
输入 银行营业时间
IF 银行营业时间<0或者>1440
Begin
输出 输入错误,请重新输入
输入 银行营业时间
IF 银行营业时间<0或者>1440
Begin
输出 输入错误,请重新输入
输入 银行营业时间
IF 银行营业时间<0或者>1440
输出 三次输入错误,退出程序
End
End输出 请输入最大到达时间间隔
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
输出 三次输入错误,退出程序
End
End输出 请输入最小到达时间间隔
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
Begin
输出 输入错误,请重新输入
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
Begin
输出 输入错误,请重新输入
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
输出 三次输入错误,退出程序
End
End输出 请输入最大交易时间
输入 最大交易时间
IF 最大交易时间>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大交易时间
IF 最大交易时间>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大交易时间
IF 最大交易时间>银行营业时间
输出 三次输入错误,退出程序
End
End输出 请输入最小交易时间
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
输出 三次输入错误,退出程序
End
End输出 请输入最小交易时间
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
输出 三次输入错误,退出程序
End
End输出 请输入最大交易额
输入 最大交易额
IF 最大交易额>银行初始金额
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最大交易额>银行初始金额
Begin
输出 输入错误,请重新输入
输入 最大交易额
IF 最大交易额>银行初始金额
输出 三次输入错误,退出程序
End
EndMaxTime<-MaxTime+随机到达间隔
While CurrentTime<CloseTime
Begin
CurrentTime<-CurrentTime+1
If DealTime<CurrentTime DealTime<-CurrentTime
If DealTime等于CurrentTime                        State<-1
IF CurrentTime等于MaxTime)
Begin调用ClientArrive()
MaxTime<-MaxTime+随机到达间隔+ClientArriveMinTime
End
IF state等于1&&Q1头指针不等于NULL
Begin  IF Q1头结点的Amount大于等于 0
Begin  调用InAmount()                         调用DealQ2()                          NeedIn<-NeedIn+1  EndElSe
Begin
调用InAmount()                    NeedIn<-NeedIn+1  End
End
End 输出     客户序列 换列  事件类型    换列  处理金额    换行
While Event头结点不为空
Begin
IF Event头结点的Type等于 "离开"
Begin  输出 换列  Event头结点的num    换列  离开  Event头结点的EndTime        换列  Event头结点的Amount     换行 IF Event头结点的Amount大于等于0               t1<-t1+1              Else                      t3<-t3+1                  End  Else
Begin  输出 换列   Event头结点的num    换列  到达  Event头结点的EndTime        换列  Event头结点的Amount     换行 IF Event头结点的Amount大于等于0                 t2<-t2+1              Else                        t4<-t4+1    SuccessIn<-NeedIn-(t2-t1) SuccessOut<-NeedOut-(t4-t3)  调用DeQueue(Event)End While Q1的头结点等于NULL
Begin                                                           BankAmountTime<-BankAmountTime+(CloseTime-Q1头结点的BeginTime)  counter<-counter+1;  调用DeQueue(Q1);  End
换行
输出 需要存款的客户人数
输出 需要取款的客户人数
输出 成功办理存款的客户人数
输出 成功办理取款的客户人数
输出 存款成功办理率
输出 取款成功办理率
输出 客户进入系统平均时间
输出 银行当前余额
End
If 操作数等于0
退出模拟系统
Return 0
End
3.4.2代码表示
int main(){ system("color 70");BankOutLook();  int n,t1=0,t2=0,t3=0,t4=0,m=0;scanf("%d",&n);  while(n==1){  srand(time(NULL));                          //初始化随机函数  printf("   请输入银行的初始存款:");  scanf("%d",&BankAmount);   if(BankAmount<0){                          printf("   输入错误!初始存款不能小于0!请再次输入!\n");   printf("   请输入银行的初始存款:");  scanf("%d",&BankAmount);   if(BankAmount<0){       printf("   输入错误!初始存款不能小于0!请最后一次输入!\n");  printf("   请输入银行的初始存款:");  scanf("%d",&BankAmount);   if(BankAmount<0){ printf("   三次输入都错误!请按任意键退出!\n");  getch();   goto end;   }  }  }  printf("   请输入银行的营业时间:");  scanf("%d",&CloseTime);  if(CloseTime>=1440){                 printf("   输入错误!一天的营业时间不能超过1440分钟(24个小时)!请再次输入!\n");  printf("   请输入银行的营业时间:");  scanf("%d",&CloseTime);  if(CloseTime>=1440){   printf("   输入错误!一天的营业时间不能超过1440分钟(24个小时)!请最后一次输入!\n");  printf("   请输入银行的营业时间:");  scanf("%d",&CloseTime);  if(CloseTime>=1440){   printf("   三次输入都错误!请按任意键退出!\n");  getch();    goto end;  }  }  } printf("   请输入最大到达时间间隔:");   scanf("%d",&ClientArriveMaxTime);  if(ClientArriveMaxTime>CloseTime){         printf("   输入错误!最大到达时间间隔必须小于营业时间!请再次输入!\n");  printf("   请输入最大到达时间间隔:");   scanf("%d",&ClientArriveMaxTime);  if(ClientArriveMaxTime>CloseTime){   printf("   输入错误!最大到达时间间隔必须小于营业时间!请最后一次输入!\n");  printf("   请输入最大到达时间间隔:");   scanf("%d",&ClientArriveMaxTime);  if(ClientArriveMaxTime>CloseTime){  printf("   三次输入都错误!请按任意键退出!\n");  getch();   goto end;  }   }  }  printf("   请输入最小到达时间间隔:");   scanf("%d",&ClientArriveMinTime);  if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){       printf("   输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请再次输入!\n");   printf("   请输入最小到达时间间隔:");   scanf("%d",&ClientArriveMinTime);  if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){  printf("   输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请最后一次输入!\n");   printf("   请输入最小到达时间间隔:");   scanf("%d",&ClientArriveMinTime);  if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){ printf("   三次输入都错误!请按任意键退出!\n");  getch();  printf("   请按任意键退出!\n");  goto end;  }   }  }   printf("   请输入最大的处理时间:");  scanf("%d",&DealMaxTime);  if(DealMaxTime>CloseTime){           printf("   输入错误!最大处理时间必须小于营业时间!请再次输入!\n");   printf("   请输入最大的处理时间:");  scanf("%d",&DealMaxTime);  if(DealMaxTime>CloseTime){  printf("   输入错误!最大处理时间必须小于营业时间!请最后一次输入!\n");   printf("   请输入最大的处理时间:");  scanf("%d",&DealMaxTime);  if(DealMaxTime>CloseTime){  printf("   三次输入都错误!请按任意键退出!\n");  getch();     goto end;  }  }  }  printf("   请输入最小的处理时间:");  scanf("%d",&DealMinTime);     if(DealMinTime<=0||DealMinTime>=DealMaxTime){printf("   输入错误!最小处理时间必须介于零和最大处理时间之间!请再次输入!\n");  printf("   请输入最小的处理时间:");  scanf("%d",&DealMinTime);     if(DealMinTime<=0||DealMinTime>=DealMaxTime){      printf("   输入错误!最小处理时间必须介于零和最大处理时间之间!请最后一次输入!\n");  printf("   请输入最小的处理时间:");  scanf("%d",&DealMinTime);     if(DealMinTime<=0 || DealMinTime>=DealMaxTime){  printf("   三次输入都错误!请按任意键退出!\n");  getch();   goto end;  }  }  }  printf("   请输入交易额的最大上限:");  scanf("%d",&MaxAmount);  if(MaxAmount>=BankAmount||MaxAmount>50000){  printf("   输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请再次输入!\n");  printf("   请输入交易额的最大上限:");  scanf("%d",&MaxAmount);  if(MaxAmount>=BankAmount||MaxAmount>50000){  printf("   输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请最后一次输入!\n");  printf("   请输入交易额的最大上限:");  scanf("%d",&MaxAmount);  if(MaxAmount>=BankAmount||MaxAmount>50000){  printf("   三次输入都错误!请按任意键退出!\n");  getch();  goto end;  }  } }  MaxTime +=rand()%(ClientArriveMaxTime-ClientArriveMinTime+1)+ClientArriveMinTime; //随机生成介于最大到达时间间隔和最小到达时间间隔之间的首次到达时间  while(CurrentTime<CloseTime){                   //当前时间小于营业时间  CurrentTime++;  if(DealTime<CurrentTime) DealTime=CurrentTime ;  if(DealTime==CurrentTime)                   //有窗口在处理交易state=1;  if(CurrentTime==MaxTime){                   //到达事件  ClientArrive();  //随机生成介于最大到达时间间隔和最小到达时间间隔之间的到达时间MaxTime+=rand()%(ClientArriveMaxTime-ClientArriveMinTime+1)+ClientArriveMinTime;  }  if(state==1&&Q1.front!=NULL){  if(Q1.front->Amount>= 0){  InAmount();                     //调用存款函数  DealQ2();                           //调用搜索处理函数  NeedIn++;  }  else{   InAmount();                     //调用取款函数  NeedOut++;  }  }  }  printf("     客户序列\t      事件类型         时间          处理金额\n");  while(Event.front!=NULL){                       //清除事件队列  if(Event.front->Type=="离开"){  printf("\t%d\t\t离开\t\t%d\t\t%d\n",Event.front->num, Event.front->EndTime,Event.front->Amount);  if(Event.front->Amount>=0)              //成功存款人数t1++;             else                                //成功取款人数t3++;                 }  else{  printf("\t%d\t\t到达\t\t%d\t\t%d\n",Event.front->num, Event.front->BeginTime,Event.front->Amount);  if(Event.front->Amount>=0)              //需要存款人数t2++;             else                                //需要取款人数 t4++;                }  SuccessIn=NeedIn-(t2-t1);  SuccessOut=NeedOut-(t4-t3);  DeQueue(Event);  }  while(Q1.front!=NULL){
//更新结束时第一队列中未处理的客户  BankAmountTime+=(CloseTime-Q1.front->BeginTime);   counter++;  DeQueue(Q1);  }  printf("\n");   printf("    需要存款的客户人数:%d\n",NeedIn);  printf("    需要取款的客户人数:%d\n",NeedOut);  printf("    成功办理存款的客户人数:%d\n",SuccessIn);  printf("    成功办理取款的客户人数:%d\n",SuccessOut);  printf("    存款成功办理率:%f\n",float(SuccessIn*100)/NeedIn);  printf("    取款成功办理率:%f\n",float(SuccessOut*100)/NeedOut);  printf("    客户逗留平均时间为:%f\n",float(BankAmountTime)/counter);  printf("    银行当前余额:%d\n",BankAmount);  printf("    请按任意键退出!\n");  break;  }  if(n==0)   printf("请按任意键退出!\n");  end:getch();  return 0;
}  

3.5函数调用关系及程序流程
以下为程序的大致流程图:

函数调用关系图如下:

4.调试分析
4.1调试中遇到的问题
调试中遇到的问题不是很多,但遇到的问题在一定程度上让我更加的了解整个程序的运作机理,对于理解数据结构也有很大的帮助。
主要的问题在于一开始的时候实现检查Q2队列的接口时,在进行检查后,未再让经过检查却不满足处理的元素重新进入Q2队列,导致最后的元素缺少。经过调试发现了这个问题,对代码进行修正,最终解决了问题。
4.2算法分析

4.3经验体会
通过这次的课程设计的编写,学会了在多种数据结构之间进行巧妙的结合运用。同时,对于用到的多种数据结构也有了更多的了解。
在测试功能的时候一定要注意选取的测试数据的正确性和实用性。
5.用户使用说明
在进入银行业务模拟界面时,选择操作编号,0-退出系统,1-进入模拟系统.
进入模拟系统后,输入的银行初始存款必须大于0;
输入的银行营业时间必须大于0且必须小于1440(一天);
输入的最大到达时间间隔必须大于0且必须小于银行营业时间;
输入的最小到达时间间隔必须大于0且必须小于最大到达时间间隔;
输入的最大处理时间必须大于0且必须小于银行营业时间;
输入的最小处理时间必须大于0且必须小于最大处理时间;
输入的交易额的最大上线必须大于0且必须小于银行初始存款且必须小于50000;
若输入有误会进行提示,三次错误后退出模拟系统。若输入无误,则开始进行输出,输出事件处理的列表信息,以及需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。

6.测试结果
6.1输出测试1
输入较大的银行初始存款,输入较大的到达时间间隔和较大的处理时间,较小的交易额上限

由于到达时间间隔和处理时间输入较大,测试数据会比较少,相对于来说,求得的银行业务模拟的客户平均用时等信息可能就没有那么的精确

6.2输出测试2

输入较大的银行初始存款,输入较小的到达时间间隔范围,较小的交易额上限

在较小的到达时间间隔和处理时间的输入下,会得到比前一种情况更多的测试数据输出,在此情况下,样本的容量足够大,对于客户平均用时等信息的统计就可能会更加的精确一些




6.3输出测试3
输入较小的银行初始存款,较大的处理时间和较大的时间间隔,较大的交易金额上限。

在这样的输出下,对于客户平均用时的影响比较大,且只能产生少量的数据。

7.参考文献

参考文献
[1] 张小艳,龚尚福编著. 数据结构与算法. 徐州:中国矿业大学出版社,2007
[2] 严蔚敏,吴伟民编著. 数据结构(C语言版). 北京: 清华大学出版社,1997
[3] 谭浩强编著. C程序设计(第三版). 北京: 清华大学出版社,2005

更多请查看我的个人博客:https://beatjerome.github.io

数据结构-银行业务模拟系统相关推荐

  1. 数据结构算法模拟系统

    一.前言 学习数据结构已经有很长时间了,加上之前搞过一段时间的ACM,虽然搞得并不怎么样吧,但是喜欢的东西不能放弃,一直打算写一个算法模拟系统,对常用的一些算法进行简单的模拟,于是我的毕业设计就这样诞 ...

  2. 银行业务队列简单模拟Java程序设计_PTA 数据结构 银行业务队列简单模拟

    仅供参考,请勿粘贴 设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 -- 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客.给定到达银行的顾客序列,请按业务完 ...

  3. 银行业务模拟系统的设计与实现

    [实验目的] 了解离散事件的模拟机制(模拟银行系统): 掌握队列的基本操作,加深对队列数据结构的理解: 加强抽象数据类型的能力. [实验原理] 创建队列类的定义,时间类和银行类的定义. 队列的每个元素 ...

  4. 八大排序算法之快速排序(下篇)(快排的优化+非递归快排的实现)

    目录 一.前言 1.快速排序的实现: 快速排序的单趟排序(排升序)(快慢指针法实现):​ 2.未经优化的快排的缺陷 二.快速排序的优化 1.三数取中优化 优化思路: 2. 小区间插入排序优化 小区间插 ...

  5. 【Java相关的项目】2022最强毕业设计选题参考,包含了JSP项目,SSH项目,SSM项目还有Springboot项目

    基于jsp+Spring+hibernate+struts2的SSH招聘网站源码代码,包含设计文稿 基于jsp+mysql的网络教学平台源码代码(设计文稿+答辩PPT+开题报告) 基于jsp+Spri ...

  6. 数据结构实验:城市交通咨询模拟系统

    一. 实验目的 1.目的:掌握图的存储.构建.搜索等操作和应用,能用最短路径及其搜索等算法编制较综合性的程序,求解最优路线问题,进行程序设计.数据结构和算法设计等方面的综合训练. 2.任务:设计一个城 ...

  7. 数据结构--简易图书管理模拟系统

    数据结构–简易图书管理模拟系统 [实验目的] 插入.查找和删除等数据操作在实际应用中非常普遍,通过设计和实现一个简易的图书管理系统,进一步提高学生对插入.查找和删除等操作的理解和应用能力.帮助学生理解 ...

  8. c语言编写银行业务模拟程序,C语言数据结构实现银行模拟

    C语言数据结构实现银行模拟 实现代码: #include #include #include #define MAX_WIN 20 #define MAX_STAY 100 typedef struc ...

  9. 数据结构实验-停车场模拟系统

    说明: 在大二小学期,老师布置了一个数据结构实验,小组成员花了大概一周完成了实验,如果代码有bug,望指出,谢谢. 问题描述: 模拟一个停车场系统.停车场根据停车的占地面积进行收费.我们假设一个停车场 ...

  10. C语言去括号编程题,数据结构课件.ppt

    <数据结构课件.ppt>由会员分享,可在线阅读,更多相关<数据结构课件.ppt(750页珍藏版)>请在人人文库网上搜索. 1.数 据 结 构,2 数据结构题集 ( C语言版) ...

最新文章

  1. 指针-数组传参,指针传参
  2. LLVM language 参考手册 翻译停止相关
  3. javascript对于DOM加强
  4. Java并发容器,底层原理深入分析
  5. 第十章 Scala 容器基础(二十二):合并有序集合
  6. 三星note9刷android11,【极光ROM】-【三星NOTE9 N960X-845】-【V17.0 Android-Q-TG1】
  7. 在MySQL登录时出现Access denied for user ‘root‘@‘localhost‘ (using password: YES) 拒绝访问问题解决
  8. CentOS快速安装、配置Web服务器(Apache)
  9. DNA甲基化经CTCF和黏连蛋白复合体调节RNA可变剪切
  10. 我的世界服务器空岛删除怎么找回,我的世界-删除空岛指令 岛屿删除指令分享...
  11. 知网研学打不开?一片空白怎么办?一步解决
  12. spell拼音码的写法及语句
  13. 靖哥哥教你如果拦截去除弹窗广告
  14. PhotoShop修改图片文字
  15. 铁路 计算机系统维护,成都市计算机学校计算机系统维护就业前景
  16. Linux 解压,压缩文件--tar 命令
  17. MayaDay3模型模块:插入循环边
  18. 不动点(Fixed Point)
  19. 2021年危险化学品生产单位主要负责人考试试卷及危险化学品生产单位主要负责人作业模拟考试
  20. 2020年6月程序员工资统计,平均14404元

热门文章

  1. 【读书笔记】合理的设计
  2. igraph基本使用方法示例
  3. 就国内而言,读大学的意义是什么?
  4. 基于Echarts的数据可视化大屏系统设计分享
  5. 分享可用的谷歌学术(google scholar) hosts
  6. 初中毕业也能月薪过万!5个质量极高的教程网站,免费献给你
  7. 聊聊NPS-提升用户体验的终极问题
  8. win系统安装夜神模拟器、夜神模拟器链接到HbuilderX
  9. git push 报错 remote: error: hook declined to update
  10. springboot 实现自动屏蔽敏感词过滤器