银行业务活动模拟
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《数据结构与算法设计》课程设计报告
题目:银行业务活动模拟
学生姓名:
学号:
班级:
指导教师:
2014年1 月8 日
一、课程设计目的
本课程设计的目的考察学生对常见数据结构及相关算法的综合应用能力,达到理论与实际应用相结合,使同学们能够根据数据对象的特性,学会数据组织的方法,解决实际问题中数据的合理存储表示,并根据相应的存储结构设计效率较高的算法实现对问题的求解;通过此次课程设计进一步培养学生良好的程序设计技巧和分析问题解决问题的能力。
二、课程设计题目
银行业务活动的模拟
任务:假设某银行有4个窗口对外接待客户,从早晨银行开门起不断有客户进入银行,由于每个窗口在某个时刻只能接待一个客户。
因此在客户人数众多时需要在每个窗口前顺次排队,对于刚进入银行的客户。
如果某个窗口的业务员正空闲,则可上前输业务。
反之,若个窗口均有客户所占,他便会排在为数最少的队伍后面。
编制一个程序模拟银行的这种业务活动并计算一天中客户在银行的平均逗留时间。
功能要求:
1).实现数据的输入;
2).各个窗口数据的访问和输出;
3)当前窗口的人员分布情况动态显示。
界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。
存储结构:学生自己根据系统功能要求自己设计。
请在最后的上交资料中指明你用到的存储结构;
测试数据:要求使用1、全部合法数据;2、整体非法数据;3、局部非法数据。
进行程序测试,以保证程序的稳定。
三、需求分析
为了计算平均时间,就要掌握每个客户到达银行和离开银行这两个时刻,后者减去前者即为每个客户在银行逗留的时间。
所有客户逗留时间的总和被一天内进入银行的客户数除便是所求的平均时间。
事件的主要信息是事件类型和事件发生的时刻,算法中要处理的事件有两类:一类是客户到达的时间,另一类是客户离开的时间。
前一类事件发生的时刻随客户到来自然形成,后一类事件发生时刻则由客户事务所需时间和等待所耗时间而定。
由于驱动程序是按时间发生时刻的先后顺序进行,则事件表应该是有序表,其主要操作时插入和删除事件。
模拟程序中需要的另一种数据结构是表示客户排队的队列,由于前面假设银行有四个窗口,一次程序中需要有四个队列,队列中有关客户的信息是客户到达的时刻和客户办理事务所需的时间。
每个队列中的队头客户即为正在窗口办理业务的顾客,他办完业务离开的时刻就是即将发生的客户离开事件的时刻,就是说,每个队头客户都存在一个将要驱动的客户离开事件。
因此,在任何时刻即将发生的事件只有五种:(1)新的顾客到达;(2)1号窗口顾客离开;(3)2号窗口顾客离开;(4)3号窗口顾客离开(5)4号窗口顾客离开。
四、总体设计
由于在实际的银行中,客户到达的时刻及其办理事务所需时间都是随机的,在模拟程序中可用随机数代替,不失一般性。
假设第一个客户进门的时刻为0,即是模拟程序处理的第一个事件,之后每个客户到达的时刻在前一个客户到达时设定。
因此在客户到达事件发生时需先产生两个随机数:其一为此时刻到达的客户办理事务所需时间durtime;其二为下一个客户将到达的时间间隔spacetime,假设当前事件发生的时刻为occurtime,则下一个客户到达事件发生的时刻为occurtime+spacetime。
由此应产生一个新的客户到达时间插入表;刚到达的客户则应插入到当前所含元素最少的队列中;若该队列在插入前为空,则还应产生一个客户离开事件插入事件表。
客户离开时间的处理比较简单。
首先计算该客户在银行逗留的时间,然后从队列中删除该客户后查看队列是否为空,若不空则设定一个新的队头客户离开事件。
五、详细设计及其实现
注:本程序在visual studio 2012上编译、调试及运行,所用的数据结构有链表、队列等。
//head.h
#ifndef _HEAD_H
#define_HEAD_H
#define winnum 4//窗口数
typedef struct{
int occurtime;//事件的发生时间
int eventtype;//事件类型,winnum表示客户到达事件,0--winnum-1表示各个窗口的离开事件
}event,elemtype;
typedef struct lnode{ //链表结点类型
elemtype data;
struct lnode * next;
}*link,*position;
struct linklist{//链表
link head,tail;
int len;
};
typedef struct{ //队列的数据元素
int arrivetime;//到达时间
int duringtime;//办理业务所需的时间
}qelemtype;
typedef struct qnode{//队列的结点
qelemtype data;
struct qnode * next;
}*queueptr;
struct linkqueue{//队列
queueptr front,rear;//队头、队尾指针
};
//对链表的操作
int initlist(linklist &l);//初始化链表
int dellinklist(linklist &l,link h,link &q);//删除第一个结点
elemtype getelem(link p);//返回指针p所指的数据元素的值
int listempty(linklist l);//判断链表是否为空
int listlength(linklist l);//求链表的长度
position gethead(linklist l);//返回链表中头结点的位置
int insertlinklist(linklist&l,elemtype e,int (*comp)(elemtype,elemtype));
//已知l为有序的线性表,将元素e按非降序插入l中
//对队列的操作
int initqueue(linkqueue &q);//初始化队列
int queueempty(linkqueue q);//判断是否为空
int queuelength(linkqueue q);//求队列的长度
int getqhead(linkqueue q,qelemtype &e);//取队头操作
int insertqueue(linkqueue &q,qelemtype e);//将元素e插入队尾
int delqueue(linkqueue &q,qelemtype &e);//删除队头操作
int minqueuenum(linkqueue q[]);//求最短队列的序号
//有关业务活动的操作
int compare(event a,event b);//比较事件a、b发生的时间,分别返回-1,0,1 void startbusiness();//银行开始营业,进行相关的初始化操作
void random(int &d,int &i);//产生随机数
void clientarrive();//客户到达时间的处理
void clientleave();//客户离开的处理
void bankbusiness();//银行业务活动模拟
void menusurface();//菜单界面
#endif
//linklistfun.cpp
#include<iostream>
#include"head.h"
using namespace std;
int initlist(linklist &l){//初始化链表
link p;
p=(link)malloc(sizeof(lnode));//生成头结点
if(p){
p->next=NULL;
l.head=p;
l.tail=p;
l.len=0;
return 0;
}
else return -1;
}
int dellinklist(linklist &l,link h,link &q){//删除h所指向结点后面的第一个结点
q=h->next;
if(q){//若链表不为空
h->next=q->next;
if(!h->next)
l.tail=h;
l.len--;
return 0;
}
else return -1;//链表为空
}
elemtype getelem(link p){//返回指针p所指的数据元素的值
return p->data;
}
int listempty(linklist l){//判断链表是否为空
if(l.len==0)//链表为空
return 0;
else
return -1;//链表非空
}
int listlength(linklist l){//求链表的长度
return l.len;
}
position gethead(linklist l){//返回链表中头结点的位置
return l.head;
}
int insertlinklist(linklist&l,elemtype e,int (*comp)(elemtype,elemtype)){//用指向函数的指针做函数的参数
//已知l为有序的线性表,将元素e按非降序插入l中link o,p,q;
q=l.head;
p=q->next;
while(p!=NULL&&comp(p->data,e)<0){
q=p;
p=p->next;
}
o=(link)malloc(sizeof(lnode));//生成结点
o->data=e;
q->next=o;
o->next=p;
l.len++;
if(!p)
l.tail=o;
return 0;
}
//queuefun.cpp
#include<iostream>
#include"head.h"
using namespace std;
int initqueue(linkqueue &q){//初始化队列
q.front=q.rear=(queueptr)malloc(sizeof(qnode));
if(!q.front)
return -1;//分配空间失败
q.front->next=NULL;
return 0;//初始化成功
}
int queueempty(linkqueue q){//判断是否为空
if(q.front==q.rear)
return 0;//队列为空
else
return -1;//队列非空
}
int queuelength(linkqueue q){//求队列的长度
int i=0;
queueptr p;
p=q.front;
while(q.rear!=p){
i++;
p=p->next;
}
return i;
}
int getqhead(linkqueue q,qelemtype &e){//取队头操作queueptr p;
if(q.front==q.rear)
return -1;//队列为空
p=q.front->next;
e=p->data;
return 0;
}
int insertqueue(linkqueue &q,qelemtype e){//将元素e插入队尾queueptr p;
p=(queueptr)malloc(sizeof(qnode));
if(!p)
return -1;//分配空间失败
p->data=e;
p->next=NULL;
q.rear->next=p;
q.rear=p;
return 0;
}
int delqueue(linkqueue &q,qelemtype &e){//删除队头操作queueptr p;
if(q.front==q.rear)
return -1;//队列为空,无法删除
p=q.front->next;
e=p->data;
q.front->next=p->next;
if(q.rear==p)
q.rear=q.front;
free(p);
return 0;
int minqueuenum(linkqueue q[]){//求最短队列的序号
int temp[winnum];
int i,k;
for(i=0;i<winnum;i++)
temp[i]=queuelength(q[i]);
k=0;
for(i=1;i<winnum;i++)
if(temp[i]<temp[0]){
temp[0]=temp[i];
k=i;
}
return k;
}
//eventfun.cpp
#include<iostream>
#include"head.h"
#include<time.h>
using namespace std;
typedef linklist eventlist;//定义事件链表类型
eventlist ev;//事件表
event en;//事件
event et;//事件临时变量
linkqueue q[winnum];//共有queuenum个队列
qelemtype client;//客户记录
int timesum=0,clientsum=0;//累计客户的逗留时间、客户数(初始值为0)int bankclosetime;//银行营业时间(单位是分)
int windowsum[winnum];//统计每个窗口在当天的访问量
int compare(event a,event b){//比较事件a、b发生的时间,分别返回-1,0,1 if(a.occurtime==b.occurtime)
return 0;
else if(a.occurtime<b.occurtime)
return -1;
else if(a.occurtime>b.occurtime)
return 1;
}
void startbusiness(){//银行开始营业,进行相关的初始化操作int i;
initlist(ev);//初始化事件表
en.occurtime=0;
en.eventtype=winnum;//到达
insertlinklist(ev,en,compare);//插入事件表
for(i=0;i<winnum;++i)
initqueue(q[i]);//初始化各个队列
}
void random(int &d,int &i){//产生随机数
//srand((unsigned)time(NULL));//srand()函数产生一个以当前时间开始的随机种子
d=rand()%30+1;//1到30之间的随机数(每个客户办理业务的时间)
//srand((unsigned)time(NULL));
i=rand()%5+1;//1到5之间的随机数(每个客户到达的时间间隔)
}
void clientarrive(){//客户到达事件的处理en.eventtype=queuenum;
qelemtype cli;
int durtime,spacetime,i;
cout<<"有一个客户进入,";
++clientsum;
random(durtime,spacetime);//产生随机数
et.occurtime=en.occurtime+spacetime;//下一个客户到达时刻
et.eventtype=winnum;//队列中只有一个客户到达事件
if(et.occurtime<bankclosetime)//银行尚未关门,插入事件表insertlinklist(ev,et,compare);
i=minqueuenum(q);//求长度最短的队列
cli.arrivetime=en.occurtime;
cli.duringtime=durtime;
insertqueue(q[i],cli);//到最短的队伍去排队
windowsum[i]++;//统计窗口i的人数
cout<<"到服务窗口"<<i+1<<"排队,";
cout<<"到达时间为"<<cli.arrivetime;
cout<<",所需时间为"<<cli.duringtime<<endl;
if(queuelength(q[i])==1){
et.occurtime=en.occurtime+durtime;
et.eventtype=i;
insertlinklist(ev,et,compare);//设定第i队列的一个离开事件并插入事件表
}
}
void clientleave(){//客户离开的处理即en.eventtype<queuenum int i;
i=en.eventtype;
delqueue(q[i],client);//删除第i队列的第一个客户,并将第一个客户的信息给client
cout<<"服务窗口"<<i+1<<"有一个客户离开了"<<endl;
timesum+=en.occurtime-client.arrivetime;//累计客户逗留时间
if(queueempty(q[i])==-1){//设定第i队列的一个离开事件并插入事件表getqhead(q[i],client);
et.occurtime=en.occurtime+client.duringtime;
et.eventtype=i;
insertlinklist(ev,et,compare);
}
}
void bankbusiness(){//银行业务活动模拟
link p;
startbusiness();//进行银行相关业务活动的初始化操作
srand((unsigned)time(NULL));//srand()函数产生一个以当前时间开始的随机种子
while(listempty(ev)==-1){
dellinklist(ev,gethead(ev),p);//删除ev链表中的第一元素(不是头结点),指针p指向了链表的第一个元素
en.occurtime=getelem(p).occurtime;
en.eventtype=getelem(p).eventtype;
if(en.eventtype==winnum)
clientarrive();//处理客户到达事件
else
clientleave();//处理客户离开事件
}
}
void menusurface(){//菜单界面
cout<<endl<<endl<<endl<<endl<<endl<<endl;
cout<<"
*****************************************"<<endl;
cout<<" 欢迎进入银行业务模拟系统"<<endl;
cout<<"
*****************************************"<<endl;
cout<<" 1.输入数据"<<endl;
cout<<" 2.查看顾客流动情况"<<endl;
cout<<" 3.数据汇总"<<endl;
cout<<" 4.退出程序"<<endl;
cout<<"请输入您的选项(整数0——4):";
}
void main(){
system("color f0");
int mark=0;//用于标记case2是否执行
while(1){
int i;
menusurface();
cin>>i;
switch(i){
case 1:
system("cls");
cout<<"请输入银行营业时间的长度(单位:分钟):";
cin>>bankclosetime;
cout<<"输入成功!"<<endl<<endl;
system("pause");
system("cls");
break;
case 2:
system("cls");
if(bankclosetime==0){
cout<<"您还没有输入数据(银行的营业时间)!"<<endl<<endl;
system("pause");
mark=1;//改变mark的值
break;
}
cout<<"当天各个窗口的顾客分布及流动情况如下:"<<endl;
bankbusiness();
cout<<endl;
system("pause");
system("cls");
break;
case 3:
system("cls");
if(bankclosetime==0){
cout<<"您还没有输入数据(银行的营业时间)!"<<endl<<endl;
system("pause");
break;
}
if(mark==0){
cout<<"您还没有执行选项2!"<<endl;
system("pause");
system("cls");
break;
}
cout<<"银行的营业时间为:"<<bankclosetime<<"分"<<endl;
cout<<"当天的顾客总数为:"<<clientsum<<",各个窗口的人数分布情况如下:"<<endl;
for(int x=0;x<winnum;x++){
cout<<"窗口"<<x+1<<":"<<windowsum[x]<<"人"<<endl;
}
cout<<"所有顾客共耗时:"<<timesum<<"分"<<endl;
cout<<"平均每人耗时:"<<timesum/clientsum<<"分"<<endl<<endl;
system("pause");
system("cls");
break;
case 4:
system("cls");
cout<<"制作信息如下:"<<endl;
cout<<"姓名:**"<<endl;
cout<<"班级:********"<<endl;
cout<<"学号:*********"<<endl<<endl;
exit(0);
break;
default:
system("cls");
cout<<"输入有误,请重新输入!"<<endl;
}
}
}
六、程序测试
注:本程序运行时为白色背景黑色字体,在此为了截图方便,采用常规的黑色背景白色字体。
(1)展示主界面。
(2)输入错误数据,如9
有错误提示:
(3)未输入1,而直接输入2
有错误提示,并带有清屏功能:
(4)未输入数据1,而直接输入3
清屏,并有错误提示
(5)按任意键回到主界面,然后输入1
清屏,并有提示
输入480(任意大于0的整数)
提示输入成功
按任意键返回主菜单
(6)未输入2,而直接输入3
清屏,并有错误提示
之后按任意键返回主菜单。
(7)输入2
为方便排版,缩小截图
按任意键返回主菜单
(8)回到主菜单后输入数据3 清屏,跳转界面
按任意键返回主菜单。
(9)回到主界面,输入1
然后输入-100
有错误提示
同理输入1500
(10)
再测试几组数据如400,600,观察数据是否是随机的
600
(11)回到主菜单,输入
4
显示制作信息
按任意键结束
八、评分标准
项目内容满分实评
选题能结合所学课程知识、有一定的能力训练。
符合选题要求
(5人一题)
10 工作量适中,难易度合理10
能能熟练应用所学知识,有一定查阅文献及运用文献资料能力10。