银行业务模拟系统.docx
《银行业务模拟系统.docx》由会员分享,可在线阅读,更多相关《银行业务模拟系统.docx(22页珍藏版)》请在冰豆网上搜索。
银行业务模拟系统
数据结构课程设计报告
(1)
题目:
银行业务模拟系统
姓名:
丘锋伟
学号:
2003040140224
班级:
计算机科学与技术03级
(2)班
指导老师:
吴伟民
完成日期:
2005年6月26日
一.需求分析
1.银行营业初拥有资本为:
TotalAmount(元),营业时间为:
CloseTime(分钟),这两个模拟参数由测试用户设定.
2.客户业务分为两种:
第一种是申请从银行得到一笔资金,即取款或贷款;第二种是向银行投入一笔资金,即存款或还款.
3.银行有两个服务窗口,相应地有两个队列.客户到达银行先排第一个队.处理每个客户业务时,如果属于第一种,且申请额超出银行现存资金总额而得不到满足时,则立刻排入第二个队等候,直至满足时才离开银行;否则业务处理完后立刻离开银行.
4.每接待完一个第一种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的队尾.假设检查不需要时间,在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待前的数额,或者本次已将第二个队列检查或处理了一遍就停止检查,转而继续接待第一个队列的客户.
5.任何时刻都只开一个窗口,营业时间结束时所有客户立即离开银行.
二.概要设计
1.设定有序事件链表的抽象数据类型定义:
ADTEventList{
数据对象:
D={ai|ai∈Event,i=1,2,···,n,n≥0}
数据关系:
R1={|ai-1,ai∈Event,ai-1<ai,i=2,3,···,n}
基本操作:
InitEVList(&EV)
操作结果:
构造一个空的有序事件链表EV.
EmptyEV(&EV)
初始条件:
有序事件链表EV已存在.
操作结果:
若EV为空,返回1;否则返回0.
cmp(a,b)
初始条件:
事件a和b已存在.
操作结果:
若a先发生,返回1;若同时发生,返回0否则返回-1;
OrderInsert(&EV,&en,cmp())
初始条件:
有序事件链表EV已存在,en为驱动事件.
操作结果:
驱动事件按时间有序插入事件链表中.
DelFirstEV(&EV,&en)
初始条件:
有序事件链表EV已存在,en为驱动事件变量.
操作结果:
删除EV中的第一个结点并以en返回其值.
}ADTEventList
2.设定客户信息队列的抽象数据类型定义:
ADTQueueList{
数据对象:
D={ai|ai∈QueueElem,i=1,2,···,n,n≥0}
数据关系:
R1={|ai-1,ai∈QueueElem,i=2,3,···,n}
基本操作:
InitQuList(&Queue)
操作结果:
构造一个空队列.
EmptyQueue(&Queue)
初始条件:
队列已存在.
操作结果:
若队列为空,返回1;否则返回0.
GetHead(Queue,&customer)
初始条件:
队列已存在.
操作结果:
若队列不空,则以customer返回队头元素.
EnQueue(&Queue,customer)
初始条件:
队列已存在.
操作结果:
新元素customer入队列.
DelQueue(&Queue,&customer)
初始条件:
队列已存在.
操作结果:
队头元素出队列,并以customer返回其值.
}ADTQueueList
3.本程序包含三个模块
1主程序模块:
voidmain()
{
输出主界面;
选择操作:
进入业务模拟窗口/退出程序;
进入业务模拟窗口:
{
输出业务模拟窗口;
选择操作:
银行业务模拟/返回主界面/退出程序;
银行业务模拟:
{
输入模拟参数;
输出业务模拟结果窗口;
}
返回主界面:
退出程序:
}
退出程序:
}
②客户到达事件处理模块――实现客户信息队列的抽象数据类型.
③客户离开事件处理模块――实现有序事件链表的抽象数据类型.
三.详细设计
1.有序事件链表类型
structEvent//驱动事件
{
intOccurtime;//事件发生时间
intNType;//事件类型
Event*next;
};
typedefEvent*EventList;
voidInitEVList(EventList&EV);
//事件初始化函数
intEmptyEV(EventList&EV);
//判断有序链表是否为空
intcmp(Eventa,Eventb);
//事件发生时间比较函数
VoidOrderInsert(EventList&EV,Event&en,int(*cmp)(Event,Event));
//驱动事件按时间有序插入事件链表函数
voidDelFirstEV(EventList&EV,Event&en);
//取出并删除事件链表中的第一个结点
2.客户信息队列类型
structQueueElem//客户信息
{
intArrtime;//客户到达时间
intDuration;//客户交易时间
intAmount;//客户交易金额
QueueElem*next;
};
structQueueList//交易客户队列
{
QueueElem*front;//队头
QueueElem*rear;//队尾
intCount;
};
typedefQueueList*QuListArray;
voidInitQuList(QueueList&Queue);
//初始化队列函数
intEmptyQueue(QueueList&Queue);
//判断队列是否为空
intGetHead(QueueListQueue,QueueElem&customer);
//获得队头元素函数
voidEnQueue(QueueList&Queue,QueueElemcustomer);
//入队列函数
voidDelQueue(QueueList&Queue,QueueElem&customer);
//出队列函数
3.三个宏定义:
#defineCounter3
//队列数组的最大值,其中数组[0]置空
#defineMax10000000000
//设定一个用于比较的最大值
#definenull0
4.定义全局变量:
intCloseTime,TotalAmount0,TotalAmount;
//银行的营业时间和营业总资本
intTotalTime,CustomerNum0,CustomerNum;
//客户们在银行花费的累计时间和客户总数
intLargeAmount=0,intDealAmount=0,intUndealAmount1=0,intUndealAmount2=0;
//交易额的最大规模,已处理的交易额规模和队列1,队列2未处理的交易额规模
intDealCustomerNum=0,UndealCustomerNum1=0,intUndealCustomerNum2=0;
//已处理的客户数目和队列1,队列2未处理的客户数目
intMin=Max,Tag=0;
//等候客户中要交易的最低金额和营业结束标志
5.声明全部函数:
voidInitQuList(QueueList&Queue);
//初始化队列函数
intGetHead(QueueListQueue,QueueElem&customer);
//获得队头元素函数
voidEnQueue(QueueList&Queue,QueueElemcustomer);
//入队列函数
voidDelQueue(QueueList&Queue,QueueElem&customer);
//出队列函数
voidInitEVList(EventList&EV);
//事件初始化函数
intcmp(Eventa,Eventb);
//事件发生时间比较函数
voidOrderInsert(EventList&EV,Event&en,int(*cmp)(Event,Event));
//驱动事件按时间有序插入事件链表函数
voidOpenForDay(EventList&EV,Event&en,QuListArray&q);
//营业模拟初始化函数
intEmptyQueue(QueueList&Queue);
//判断队列是否为空
voidNextLeaver(EventList&EV,Event&en,QuListArray&q);
//确定下一个驱动事件函数
voidCustomerArrived(EventList&EV,Event&en,QuListArray&q);
//客户到达事件处理函数
voidMin_amount(QueueListQ);
//获得等候队列中的客户的最低交易额
intEmptyEV(EventList&EV);
//判断有序链表是否为空
voidDelFirstEV(EventList&EV,Event&en);
//取出并删除事件链表中的第一个结点
voidCustomerDeparture(EventList&EV,Event&en,QuListArray&q);
//客户离开事件处理函数
voidLeave(QuListArray&q);
//营业时间结束后全部客户出队列函数
intPrintMainScreen();
//输出主界面窗口
voidPrintMoodScreen();
//输出业务模拟窗口
intOutput();
//输出业务模拟结果窗口
6.部分核心算法的实现:
①营业模拟初始化:
voidOpenForDay(EventList&EV,Event&en,QuListArray&q)
{
Event*temp;
temp=newEvent;
temp->NType=0;
temp->Occurtime=0;
temp->next=null;
en=*temp;
InitEVList(EV);
OrderInsert(EV,en,cmp);
for(inti=1;iTotalTime=0;
CustomerNum=0;
}
2确定下一个驱动事件
voidNextLeaver(EventList&EV,Event&en,QuListArray&q)
{
QueueElemcustomer;
if(Min<=TotalAmount)
{
GetHead(q[2],customer);
while(customer.Amount+TotalAmount<0)
{
DelQueue(q[2],customer);
EnQueue(q[2],customer);
GetHead(q[2],customer);
}
if(en.Occurtime+customer.Duration>=CloseTime)
{
Tag++;
Eventtemp={CloseTime,2,null};
OrderInsert(EV,temp,cmp);
}
else
{
Eventtemp={en.Occurtime+customer.Duration,2,null};
OrderInsert(EV,temp,cmp);
}
}
else
{
if(GetHead(q[1],customer))//
{
while(!
EmptyQueue(q[1])&&customer.Amount<0
&&customer.Amount+TotalAmount<0)
{
DelQueue(q[1],customer);
EnQueue(q[2],customer);
Min=Min<-customer.Amount?
Min:
-customer.Amount;
GetHead(q[1],customer);
}
if(!
EmptyQueue(q[1]))
{
if(en.Occurtime+customer.Duration>=CloseTime)
{
Tag++;
Eventtemp={CloseTime,1,null};
OrderInsert(EV,temp,cmp);
}
else
{
Eventtemp={en.Occurtime+customer.Duration,1,null};
OrderInsert(EV,temp,cmp);
}
}
}
}
}
3驱动事件按时间有序插入事件链表
voidOrderInsert(EventList&EV,Event&en,int(*cmp)(Event,Event))
{
Event*P,*Q;
Event*Temp=newEvent;
*Temp=en;
P=Q=EV;
P=P->next;
if(P!
=null)
{
while(P!
=null)
{
if(cmp(*P,en)==-1)
{
P=P->next;
Q=Q->next;
}
elseif(cmp(*P,en)==1)
{
Temp->next=P;
Q->next=Temp;
return;
}
elseif(cmp(*P,en)==0)
{
do
{
P=P->next;
Q=Q->next;
}while(P&&!
(cmp(*Q,*P)==-1));
Temp->next=P;
Q->next=Temp;//
return;
}
}
Q->next=Temp;
Temp->next=P;
return;
}
else
{
Q->next=Temp;
Temp->next=null;
return;
}
}
4客户到达事件处理:
voidCustomerArrived(EventList&EV,Event&en,QuListArray&q)
{
intintertime,durtime,amount,t,a,b;
srand(time(NULL));
intertime=1+rand()%30;//下个客户到达的时间间隔,不大于30分钟
dur:
durtime=1+rand()%30;//客户办理业务所要时间,不大于30分钟
if(intertime==durtime)gotodur;
a=rand()%2;
b=1+rand()%1000;
amount=a*b+(a-1)*b;//客户的存取金额,不大于1000元
t=en.Occurtime+intertime;
EventTemp={t,0,null};
if(t{
CustomerNum++;
OrderInsert(EV,Temp,cmp);
}
QueueElemcustomer={en.Occurtime,durtime,amount,null};
EnQueue(q[1],customer);
if(amount>0)//
{
LargeAmount+=amount;
}
elseLargeAmount-=amount;
if(q[1].Count==1)NextLeaver(EV,en,q);
}
5客户离开事件处理:
voidCustomerDeparture(EventList&EV,Event&en,QuListArray&q)
{
inti=en.NType;
QueueElemcustomer;
DelQueue(q[i],customer);
TotalTime+=en.Occurtime-customer.Arrtime;
TotalAmount+=customer.Amount;
if(customer.Amount>0)
{
DealAmount+=customer.Amount;
}
elseDealAmount-=customer.Amount;//
DealCustomerNum++;
if(Tag==0)
{
if(i==2)Min_amount(q[i]);
NextLeaver(EV,en,q);
}
}
6营业时间结束后全部客户离开银行:
voidLeave(QuListArray&q)
{
inti;
QueueElemcustomer;
for(i=1;i{
while(!
EmptyQueue(q[i]))
{
DelQueue(q[i],customer);
TotalTime+=CloseTime-customer.Arrtime;
if(i==1)
{
UndealCustomerNum1++;
if(customer.Amount>0)
{
UndealAmount1+=customer.Amount;
}
elseUndealAmount1-=customer.Amount;
}
if(i==2)
{
UndealCustomerNum2++;
if(customer.Amount>0)
{
UndealAmount2+=customer.Amount;
}
elseUndealAmount2-=customer.Amount;
}
}
}
}
7.主函数的实现:
voidmain()
{
loopa:
if(PrintMainScreen()==1)
{
loopb:
PrintMoodScreen();
inti;
Eventen;
EventListEV;
QueueListq[Counter];
QuListArrayQuPoint;
QuPoint=q;
LargeAmount=0,DealAmount=0,UndealAmount1=0,UndealAmount2=0;
DealCustomerNum=0,UndealCustomerNum1=0,UndealCustomerNum2=0;
Min=Max,Tag=0;
OpenForDay(EV,en,QuPoint);
while(!
EmptyEV(EV))
{
DelFirstEV(EV,en);
if(en.NType==0)
{
CustomerArrived(EV,en,QuPoint);
}
else
{
CustomerDeparture(EV,en,QuPoint);
}
}
Leave(QuPoint);
i=Output();
if(i==1)gotoloopa;
if(i==2)gotoloopb;
}
}
四.调试分析
1.调试过程中对部分模拟量作了如下规定:
①客户的存取金额,不大于1000元
②客户办理业务所要时间,不大于30分钟
③下个客户到达的时间间隔,不大于30分钟
当然,系统的模拟性能完全不受这些规定的限制,用户完全可以根据实际需要作简单的修改和调整.而且以上各模拟量均由随机函数给出,符合离散事件要求.
2.算法的时空分析:
①基于有序链表的时空分析:
时间复杂度:
由于对有序链表操作的主要时间在于插入操作的查找部分,而删除操作不需查找,只是删除第一个结点,故有:
T1(n)=O(n*n).(其中n为进入银行的客户总数.)
空间复杂度:
因为每个客户只能产生两个事件:
到达事件和离开事件,所以有序链表的总长度不可能超过客户总数的两倍,故有:
S1(n)=O(n).(其中n为进入银行的客户总数.)
②基于用户信息队列的时空分析:
时间复杂度:
因为每个客户都要且只要进入第一个队列一次,而是否进入第二个队列或是离开则是随机的.作最坏情况打算,设n1为直接离开的客户数,n2为进入第二个队列的客户数,则当n1=n2=n/2,且每次从第一队中离开一个客户,第二
个队列中的客户都要进出队列一次,则(n1*n2)|max=n*n/4,故有:
T2(n)=O(n*n).
空间复杂度:
作最坏打算,假设每个客户都要分别进入第一和第
第二个队列,则两个队列元素的最大个数为客户数量的两倍.故有:
S2(n)=O(n).
③总的时空分析:
总的时间复杂度:
T(n)=max(T1(n),T2(n))=O(n*n).
总的空间复杂度:
S(n)=S1(n)+S2(n).
五.用户手册
1.本程序的运行环境为DOS操作系统,执行文件为aaa.exe.
2.进入演示程序后,即显示文本方式的主界面窗口:
3.进入银行业务模拟系统后,显示如下界面窗口:
4.输入模拟参数后,显示如下模拟结果输出界面:
六.测试结果
测试的主要指标包括:
1.银行对客户要求的交易资金的满足率.
2.银行对要求交易的客户的满足率.
3.银行服务对客户平均时间利用率的影响.
下面是以连续模拟时间为480分钟(即8小时)的几个模拟结果:
模拟结果1:
(银行营业资本为1000元)
模拟结果2:
(银行营业资本为10000元)
模拟结果3:
(银行营业资本为100000元)
七.附录
源程序包含的头文件清单:
#include"iostream.h"
#include"stdlib.h"
#include"time.h"