数据结构 课程设计报告
班级:191113 学号:20111000611 姓名:黄建钊 指导老师:朱晓莲 日期:2013年3月
1.银行业务模拟
1.需求分析
客户的业务分为两种:第一种是申请从银行得到一笔资金,即取款或借款;第二种是向银行中投入一笔资金,即存款或还款。银行有两个服务窗口,相应地有两个队列。客户到达银行后先排第一个队。处理每个客户业务时,如果属于第一种,且申请额超出银行现存资金总额而得不到满足,则立刻排入第二个队等候,直至满足时才离开银行;否则业务处理完后立刻离开银行。每接待完一个第二种业务的客户,则顺序检查和处理(如果可能)第二个队列中的客户,对能满足的申请者予以满足,不能满足者重新排到第二个队列的队尾。注意,在此检查过程中,一旦银行资金总额少于或等于刚才第一个队列中最后一个客户(第二种业务)被接待之前的数额,或者本次已将第二个队列检查或处理了一遍,就停止检查(因为此时已不可能还有能满足者)转而继续接待第一个队列的客户。任何时刻都只开一个窗口。假设检查不需要时间。营业时间结束时所有客户立刻离开银行。 要求:写一个上述银行业务的事件驱动模拟系统,模拟出并输出系统处理所有客户的流程,并计算出所有客户在银行内逗留的平均时间。
2.设计
2.1设计思想
本问题主要需要处理两个交易队列(fq,sq)和一个事件队列(eq)。当有客户来交易时,让客户先进队列一fq,然后让事件队列eq记下客户随机产生的到达时间,如果客户办理存款,则更新银行的资金并且记下客户随机产生的逗留时间,办理完后让事件队列记录客户的离开时间,然后从队列一中删除该客户的结点;如果客户办理取款,当银行此刻的金额可以满足该客户,则更新银行的资金并且记下客户随机产生的逗留时间,办理完后让事件队列记录客户的离开时间,然后从队列一中删除该客户的结点,当银行此刻的金额不能够满足该客户,则将该客户转移到队列二等待,直到下一个办理存款的客户办理完存款后,从队列二的头结点开始搜索,看看有没有可以满足其取款的客户,如果队列二的头结点客户能满足,则为其办理取款,然后从队列二中删除该节点,并让事件队列记录该客户的离开时间,如果队列二的头结点客户仍然不能满足,则搜索下一个客户直到将队列二搜索完。等到银行的营业时间到了后,输出事件队列,需要办理两种业务的顾客数,已成功办理两种业务的顾客数,两种业务的成功办理率,客户在银行内的平均逗留时间和下班时银行所剩余的资金总额。
实现:
输入:
用户需要在程序运行开始时输入以下数据:
银行初始资金total;
银行营业时间closetime;
客户交易时间上下界dealmaxtime和dealmintime,用于给随机数产生函数传递参数,产生一个介
2
于这两个值之间的值;
客户到达时间间隔上界arrivemaxtime arrivemintime,用于给随机数产生函数传递参数,产生一个介于这两个值之间的值;
交易额的最大上限dealMaxMoney.用于给随机函产生函数参数,产生一个介于-dealMaxMoney和dealMaxMoney之间的值,作为顾客到银行办理业务的交易额,。
输出:
本程序用dos界面模拟输出整个银行业务办理及排队的结果,最后给出一下数据:
分别列出需要办理两种业务的顾客数;
分别列出已成功办理两种业务的顾客数;
分别列出两种业务的成功办理率;
客户在银行内的平均逗留时间;
下班时银行所剩余的资金总额。
(1)数据结构设计:
结构体的定义如下:
struct service
{
int num; //客户号
string type; //到达或离开
int beginTime;//到达时间
int endTime;//离开时间
int money; //正数为存款,负数为取款
service* next;//指针域
};
队列的抽象数据类型定义如下:
ADT Queue{
数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n, n≥0 }
数据关系:R1={|ai-1, ai∈D, i=2,...,n }
基本操作:
void init_Q(Queue &Q);
操作结果:构造空队列Q
int Q_empty(Queue Q);
初始条件:队列Q存在
操作结果:若Q为空队列,则返回TRUE,否则FALSE
int Q_length(Queue Q);
初始条件:队列Q存在
操作结果:返回队列Q的元素个数,即队列长度
int gethead_Q(Queue Q);
初始条件:队列Q存在
3
操作结果:返回队列Q的队头元素 void en_Q(Queue &Q,int e);
初始条件:队列Q存在
操作结果:插入元素e为Q的新的队尾元素。 void de_Q(Queue &Q,int &e);
初始条件:队列Q存在
操作结果:删除Q的队头元素。
}ADT Queue
(2)算法设计
队列类型
typedef struct QNode
{ //队列节点类型 int data;
struct QNode *next;
}QNode,*PQNode;
typedef struct {
PQNode front; //队头指针
PQNode rear; //队尾指针
}Queue;
队列的基本操作设置如下:
void init_Q(Queue &Q);
//初始化,构造空队列Q(Q.front=Q.rear) int Q_empty(Queue Q);
//若队列Q存在
//若Q为空队列,则返回TRUE,否则FALSE int Q_length(Queue Q);
//若队列Q存在
//返回队列Q的元素个数,即队列长度 int gethead_Q(Queue Q);
//若队列Q存在
//返回队列Q的队头元素
void en_Q(Queue &Q,int e);
//若队列Q存在
//插入元素e为Q的新的队尾元素。 void de_Q(Queue &Q,int &e);
//若队列Q存在
//删除Q的队头元素。
其中操作算法:
void init_Q(Queue &Q)
{
4
//初始化,构造空队列Q(Q.front=Q.rear) Q.front=Q.rear=(PQNode)malloc(sizeof(QNode)); if(!Q.front)exit(-1);
}
int Q_empty(Queue Q)
{
//若队列Q存在
//若Q为空队列,则返回TRUE,否则FALSE if(Q.front==Q.rear)return 1;
else return 0;
}
int gethead_Q(Queue Q)
{
//若队列Q存在
//返回队列Q的队头元素
if(!Q_empty(Q))return Q.front->next->data; else return 0;
}
int Q_length(Queue Q)
{
//若队列Q存在
//返回队列Q的元素个数,即队列长度 int count=0;
PQNode p=Q.front;
while(p!=Q.rear)
{
count++;
p=p->next;
}
return count;
}
void en_Q(Queue &Q,int e)
{
//若队列Q存在
//插入元素e为Q的新的队尾元素。
PQNode p=(PQNode)malloc(sizeof(QNode)); if(!p)exit(-1);
p->data=e; p->next=NULL;
Q.rear->next=p;
Q.rear=p;
}
void de_Q(Queue &Q,int &e)
{
//若队列Q存在
5
队列扫描算法
其他函数算法 //删除Q的队头元素 PQNode p; if(Q.front==Q.rear)return ; p=Q.front->next; e=p->data; Q.front->next=p->next; if(Q.rear==p)Q.rear=Q.front; free(p); } 伪代码: { if(!empry(fq)&& fq.head->money<0) //如果队列一不空,而且队头客户办理第二种业务 { //1.可以办,完成离开(即银行现金足够取) //2.不可以办,排队2等候 } else //存款 ,第一种业务 if(!empty(fq) && temped= searchAndDel(sq,total))) //当交易时间到 { //办理该业务,并开始扫描第二队列,看是否能满足 需要 } if(currentime==next_arrtime ) { //当当前时间等于即将到来的顾客到来时间,初始化 点,并设置下一顾客到达时间 } }
int rand_num(int max,int min) //随机数生成 {
6
//第二队列//该顾客节
//根据传进的max和min,生成介于max和min的一个 //整数
randomize();
RandSeed=Now();
return ( random(100000) % (max - min + 1) +min );
}
2.2设计表示
函数调用关系图
()
详细设计
int main()//主函数
{
int i;
for(i=0;i<=14;i++)< p="">
printf("\n");
printf(" **********************************************************\n"); printf(" **********************************************************\n"); printf(" *********** ***************\n"); printf(" *********** 0.退出 1.进入模拟系统 ***************\n"); printf(" *********** ***************\n"); printf(" **********************************************************\n"); printf(" **********************************************************\n"); printf(" ************************ 请选择服务 ********************\n"); int n,t1=0,t2=0,t3=0,t4=0,m=0;
scanf("%d",&n);
while(n==1)
7
{
srand(time(NULL)); //初始化随机函数
printf("请输入银行的初始存款:\n");
scanf("%d",&total);
printf("请输入银行的营业时间:\n");
scanf("%d",&closeTime);
printf("请输入最大到达时间间隔:\n");
scanf("%d",&arriveMaxTime);
printf("请输入最小到达时间间隔:\n");
scanf("%d",&arriveMinTime);
printf("请输入最大的处理时间:\n");
scanf("%d",&dealMaxTime);
printf("请输入最小的处理时间:\n");
scanf("%d",&dealMinTime);
printf("请输入交易额的最大上限:\n");
scanf("%d",&dealMaxMoney);
}
void arrive()//"到达"函数,随机产生顾客,进入队列一产生到达事件 进入事件队列 {
push(fq,(rand()% (2*dealMaxMoney) -dealMaxMoney)); //随机产生顾客加入第一队列
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;
}
void putMoney()//"存款"函数
{
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()%(dealMaxTime-dealMinTime +1)+dealMinTime);//离开时间为到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间
++counter; //更新客户总数
totalTime += (back(eq)->endTime - front(fq)->beginTime); //更新逗留时间
pop(fq); //删除第一队列第一个业务
currentTimeOfDeal = back(eq)->endTime;//交易时间为客户的离开时间
8
state =0;//窗口没有交易需要处理
}
void getMoney()//"取款"函数
{
if( (-fq.head->money) > total )//资金短缺 加入第二队列
{
push( sq,front(fq)->money );
back(sq)->beginTime = front(fq)->beginTime;
back(sq)->num = front(fq)->num;
pop(fq);
}
else
{
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()%(dealMaxTime-dealMinTime +1)+dealMinTime);//客户的离开时间为客户的到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间
back(eq)->beginTime = 0;
currentTimeOfDeal = back(eq)->endTime;//交易时间为客户的离开时间 ++counter; //更新客户总数
totalTime += ( back(eq)->endTime - back(fq)->beginTime ); //更新逗留时间 pop(fq); //删除第一队列第一个业务
state =0;//窗口没有交易需要处理
}
}
service* searchAndDeal(queue &q,int m)//"搜索"函数,在对列中寻找可处理元素 {
service* sign = q. head; //标记头节点
service* temp;
while(q. head!=NULL )
{
if((-(q. head->money))
{
if(q. head==q.rear)
{
temp = q. head;
q. head = q. rear = NULL;
return temp;
}
9
else//队首元素出列
{
temp = q. head;
q. head = q. head->next; // 首节点后移一位,返回原首节点 return temp;
}
}
else//队首元首不能被处理
{
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;
}
}
if(q. head == sign)//队列循环一周时停止
return NULL;
}
return NULL;
}
service* temped ;
int randomTemp;//
void findAndDeal()//"处理"函数,在对列中寻找可处理元素,对其进行处理 {
while( (temped= searchAndDeal(sq,total))&&temped!=NULL ) //查找可处理取款
{
total += temped->money; //更新资金总额
push(eq,temped->money); //加入事件队列
back(eq)->type = "离开";
back(eq)->num = temped->num;
randomTemp = rand()%(dealMaxTime-dealMinTime +1)+dealMinTime;//处理时间为随机产生的介于最大处理时间和最小处理时间之间的处理时间
back(eq)->endTime = currentTime + randomTemp ;//客户离开时间为当前时间加上处理时间
currentTimeOfDeal += randomTemp;//更新交易时间
++counter; //更新客户总数
totalTime += ( back(eq)->endTime - temped->beginTime ); //更新逗留时间 temped; //删除节点
10
temped = NULL;
}
state = 0;
}
3.调试分析
1.在处理顾客的第一种业务(从银行取出一笔钱)时,我没有特殊处理,仅是和处理第二种一样,即是等到该顾客交易时间结束时才开始判断,如果不够取进入第二队列等候。但题目中有“如果属于第一种,且申请额超出银行现存资金总额而得不到满足,则立刻排入第2个队等候,直至满足时才离开银行,否则业务处理完后立刻离开银行”。想想这也是符合实际。于是改算法的判断为以下算法:
伪代码:
{
if(!empry(fq)&& fq.head->money<0)< p="">
//如果队列一不空,而且队头客户办理第二种业务
{
//1.可以办,完成离开(即银行现金足够取)
//2.不可以办,排队2等候
}
else
//存款 ,第一种业务
if(!empty(fq) && temped= searchAndDel(sq,total)))
//当交易时间到
{
//办理该业务,并开始扫描第二队列,看是否能满足 //第二
队列需要
}
if(currentime==next_arrtime )
{
//当当前时间等于即将到来的顾客到来时间,初始化 //该顾
客节点,并设置下一顾客到达时间
}
}
2.对于计算客户在银行内的平均逗留时间,一直不成功,后经老师指导,
平均逗留时间算法思想如下:已成功交易的客户,逗留时间为他的离开时间
和到达时间之差,直到银行营业结束,没有成功交易的客户的逗留时间不算
入内,总的逗留时间为每个成功交易的客户的逗留时间之和,平均逗留时间
为总的逗留时间除以成功交易的客户数。
4.用户手册
11
用户按任意键继续,则会出现如下主界面:
用户选择1开始模拟。按提示输入相应的数据设置,就能得到想要的模拟结果。退出选择0.
对用户输入要求如下:
1. 银行开始的资金总额应该大于零。
2. 银行开始的资金总额应该大于零。
3. 银行的营业时间必须小于1440分钟(24小时)。
4. 最大到达时间间隔必须小于营业时间。
5. 最小到达时间间隔必须介于零和最大到达时间之间。
6. 最大处理时间必须小于营业时间。
7. 最小处理时间必须介于零和最大处理时间之间。
8. 最大交易额应该小于银行开始时的资金总额且小于程序设置的50000。 如果输入不符合上述要求,程序会提示用户哪里输入出错,可以再次输入。每个输入数据都有3次机会。当三次输入都错的时候,程序停止运行,按任意键退出。
现给出最小处理时间出错时的三种提示截图:
5.测试数据及测试结果
12
正确输入并开始模拟运行:
输入一般数据:
a. 银行初始资金total=5000
b. 银行营业时间closetime=50
c. 客户到达时间间隔上界arrivemaxtime=5和arrivemintime=3
客户交易时间上界dealmaxtime=8和dealmintime=4
13
6.源程序清单
//银行业务模拟系统
#include
#include
#include
#include
using namespace std;
struct service
{
int num; //客户号
string type; //到达或离开
int beginTime;//到达时间 int endTime;//离开时间
int money; //正数为存款,负数为取款 service* next;//指针域
};
14
struct queue //队列
{
service* head;//队列头指针
service* rear;//队列尾指针
};
int total; //初始时银行现存资金总额
int closeTime; //营业结束时间
int arriveMaxTime; //两个到达事件之间的间隔上限 int arriveMinTime; //两个到达事件之间的间隔下限 int dealMaxTime; //客户之间交易的时间上限 int dealMinTime; //客户之间交易的时间下限 int dealMaxMoney ; //交易额上限
int ndn=0;//需要存款的人数
int nwn=0;//需要取款的人数
int sdn=0;//成功存款的人数
int swn=0;//成功取款的人数
int currentTime = 0; //当前时间
int totalTime = 0; //客户逗留总时间
int counter = 0; //客户总数
int number = 1; //初始客户序列号
bool state =1; //用于判断是否有窗口在处理 int currentTimeOfDeal = 0;//交易时间
int thearriveMaxTime = 0;//最大到达时间 queue eq; //事件队列
queue fq; //队列一
queue sq; //对列二
//初始化三个队列
service* front(queue &q)//返回队首元素 {
return q. head;
}
service* back(queue &q)//返回队尾元素 {
return q. rear;
}
15
void push(queue &q,int d)//入队列函数,插入元素d为队列q的新的队尾元素
{
service* temp = new service;
temp->money = d;
temp->next = NULL;
if(q.head==NULL)//队列为空,初始化
{
q. head = temp;
q. rear = temp;
}
else//队列不为空,插入元素d
{
q. rear->next = temp;
q. rear = q.rear->next;
}
}
void pop(queue &q)// 若队列不空,出对列函数
{
service* temp;
temp = q. head;
if(q. head->next==NULL )//对列只有一个元素
q.head = q. rear =NULL;
else
q. head=q. head->next;
temp;
}
void arrive()//"到达"函数,随机产生顾客,进入队列一产生到达事件 进入事件队列 {
push(fq,(rand()% (2*dealMaxMoney) -dealMaxMoney)); //随机产生顾客加入第一队列 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;
}
16
void putMoney()//"存款"函数
{
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()%(dealMaxTime-dealMinTime +1)+dealMinTime);//离开时间为到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间
++counter; //更新客户总数
totalTime += (back(eq)->endTime - front(fq)->beginTime); //更新逗留时间
pop(fq); //删除第一队列第一个业务
currentTimeOfDeal = back(eq)->endTime;//交易时间为客户的离开时间
state =0;//窗口没有交易需要处理
}
void getMoney()//"取款"函数
{
if( (-fq.head->money) > total )//资金短缺 加入第二队列
{
push( sq,front(fq)->money );
back(sq)->beginTime = front(fq)->beginTime;
back(sq)->num = front(fq)->num;
pop(fq);
}
else
{
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()%(dealMaxTime-dealMinTime +1)+dealMinTime);//客户的离开时间为客户的到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间
back(eq)->beginTime = 0;
currentTimeOfDeal = back(eq)->endTime;//交易时间为客户的离开时间
++counter; //更新客户总数
totalTime += ( back(eq)->endTime - back(fq)->beginTime ); //更新逗留时间
pop(fq); //删除第一队列第一个业务
state =0;//窗口没有交易需要处理
}
17
}
service* searchAndDeal(queue &q,int m)//"搜索"函数,在对列中寻找可处理元素 {
service* sign = q. head; //标记头节点
service* temp;
while(q. head!=NULL )
{
if((-(q. head->money))
{
if(q. head==q.rear)
{
temp = q. head;
q. head = q. rear = NULL;
return temp;
}
else//队首元素出列
{
temp = q. head;
q. head = q. head->next; // 首节点后移一位,返回原首节点 return temp;
}
}
else//队首元首不能被处理
{
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;
}
}
if(q. head == sign)//队列循环一周时停止
return NULL;
}
return NULL;
}
service* temped ;
int randomTemp;//
18
void findAndDeal()//"处理"函数,在对列中寻找可处理元素,对其进行处理
{
while( (temped= searchAndDeal(sq,total))&&temped!=NULL ) //查找可处理取款
{
total += temped->money; //更新资金总额
push(eq,temped->money); //加入事件队列
back(eq)->type = "离开";
back(eq)->num = temped->num;
randomTemp = rand()%(dealMaxTime-dealMinTime +1)+dealMinTime;//处理时间为随机产生的介于最大处理时间和最小处理时间之间的处理时间
back(eq)->endTime = currentTime + randomTemp ;//客户离开时间为当前时间加上处理时间 currentTimeOfDeal += randomTemp;//更新交易时间
++counter; //更新客户总数
totalTime += ( back(eq)->endTime - temped->beginTime ); //更新逗留时间
temped; //删除节点
temped = NULL;
}
state = 0;
}
int main()
{
int i;
for(i=0;i<=14;i++)< p="">
printf("\n");
printf(" **********************************************************\n");
printf(" **********************************************************\n");
printf(" *********** ***************\n");
printf(" *********** 0.退出 1.进入模拟系统 ***************\n");
printf(" *********** ***************\n");
printf(" **********************************************************\n");
printf(" **********************************************************\n");
printf(" ************************ 请选择服务 ********************\n");
int n,t1=0,t2=0,t3=0,t4=0,m=0;
scanf("%d",&n);
while(n==1)
{
srand(time(NULL)); //初始化随机函数
printf("请输入银行的初始存款:\n");
scanf("%d",&total);
if(total<0)< p="">
{
printf("输入错误!初始存款不能小于0!请再次输入!\n");
19
printf("请输入银行的初始存款:\n");
scanf("%d",&total);
if(total<0)< p="">
{
printf("输入错误!初始存款不能小于0!请最后一次输入!\n");
printf("请输入银行的初始存款:\n");
scanf("%d",&total);
if(total<0)< p="">
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入银行的营业时间:\n");
scanf("%d",&closeTime);
if(closeTime>=1440)
{
printf("输入错误!一天的营业时间不能超过1440分钟(24个小时)!请再次输入!\n"); printf("请输入银行的营业时间:\n");
scanf("%d",&closeTime);
if(closeTime>=1440)
{
printf("输入错误!一天的营业时间不能超过1440分钟(24个小时)!请最后一次输入!\n");
printf("请输入银行的营业时间:\n");
scanf("%d",&closeTime);
if(closeTime>=1440)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入最大到达时间间隔:\n");
scanf("%d",&arriveMaxTime);
if(arriveMaxTime>closeTime)
{
printf("输入错误!最大到达时间间隔必须小于营业时间!请再次输入!\n"); printf("请输入最大到达时间间隔:\n");
20
scanf("%d",&arriveMaxTime);
if(arriveMaxTime>closeTime)
{
printf("输入错误!最大到达时间间隔必须小于营业时间!请最后一次输入!\n"); printf("请输入最大到达时间间隔:\n");
scanf("%d",&arriveMaxTime);
if(arriveMaxTime>closeTime)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入最小到达时间间隔:\n");
scanf("%d",&arriveMinTime);
if(arriveMinTime<=0 arrivemintime="">=arriveMaxTime)
{
printf("输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请再次输入!\n");
printf("请输入最小到达时间间隔:\n");
scanf("%d",&arriveMinTime);
if(arriveMinTime<=0 arrivemintime="">=arriveMaxTime)
{
printf("输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请最后一次输入!\n");
printf("请输入最小到达时间间隔:\n");
scanf("%d",&arriveMinTime);
if(arriveMinTime<=0 arrivemintime="">=arriveMaxTime)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入最大的处理时间:\n");
scanf("%d",&dealMaxTime);
if(dealMaxTime>closeTime)
{
printf("输入错误!最大处理时间必须小于营业时间!请再次输入!\n");
printf("请输入最大的处理时间:\n");
21
scanf("%d",&dealMaxTime);
if(dealMaxTime>closeTime)
{
printf("输入错误!最大处理时间必须小于营业时间!请最后一次输入!\n"); printf("请输入最大的处理时间:\n");
scanf("%d",&dealMaxTime);
if(dealMaxTime>closeTime)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入最小的处理时间:\n");
scanf("%d",&dealMinTime);
if(dealMinTime<=0 dealmintime="">=dealMaxTime)
{
printf("输入错误!最小处理时间必须介于零和最大处理时间之间!请再次输入!\n"); printf("请输入最小的处理时间:\n");
scanf("%d",&dealMinTime);
if(dealMinTime<=0 dealmintime="">=dealMaxTime)
{
printf("输入错误!最小处理时间必须介于零和最大处理时间之间!请最后一次输入!\n");
printf("请输入最小的处理时间:\n");
scanf("%d",&dealMinTime);
if(dealMinTime<=0 dealmintime="">=dealMaxTime)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
printf("请输入交易额的最大上限:\n");
scanf("%d",&dealMaxMoney);
if(dealMaxMoney>=total || dealMaxMoney>50000)
{
printf("输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请再次输入!\n");
printf("请输入交易额的最大上限:\n");
22
scanf("%d",&dealMaxMoney);
if(dealMaxMoney>=total || dealMaxMoney>50000)
{
printf("输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请最后一次输入!\n");
printf("请输入交易额的最大上限:\n");
scanf("%d",&dealMaxMoney);
if(dealMaxMoney>=total || dealMaxMoney>50000)
{
printf("三次输入都错误!请按任意键退出!\n");
getch();
printf("请按任意键退出!\n");
goto end;
}
}
}
thearriveMaxTime +=rand()%(arriveMaxTime-arriveMinTime + 1)+arriveMinTime; //随机生成介于最大到达时间间隔和最小到达时间间隔之间的首次到达时间
while(currentTime < closeTime)//当前时间小于营业时间
{
++currentTime;
if( currentTimeOfDeal < currentTime ) currentTimeOfDeal = currentTime ;
if( currentTimeOfDeal == currentTime ) state = 1;//有窗口在处理交易
if( currentTime == thearriveMaxTime ) //到达事件
{
arrive();
thearriveMaxTime +=rand()%(arriveMaxTime-arriveMinTime + 1)+arriveMinTime;//随机生成介于最大到达时间间隔和最小到达时间间隔之间的到达时间
}
if( state == 1 && fq.head!=NULL )
{
if(fq.head->money >= 0)
{
putMoney();//调用存款函数
findAndDeal();//调用搜索处理函数
ndn++;
}
else
{
getMoney();//调用取款函数
nwn++;
23
}
}
}
printf("客户序列 事件类型 时间 处理金额\n");
while( eq.head!=NULL ) //清除事件队列
{
if(eq.head->type=="离开")
{
printf("%d 开 %d %d\n",eq.head->num, eq.head->endTime,eq.head->money); if(eq.head->money>=0) t1++;//成功存款人数
else t3++;//成功取款人数
}
else
{
printf("%d 达 %d %d\n",eq.head->num, eq.head->beginTime,eq.head->money); if(eq.head->money>=0) t2++;//需要存款人数
else t4++;//需要取款人数
}
sdn=ndn-(t2-t1);
swn=nwn-(t4-t3);
pop(eq);
}
while( fq.head!=NULL )//更新结束时第一队列中未处理的客户
{
totalTime += ( closeTime - fq.head->beginTime );
++counter;
pop(fq);
}
printf("\n");
printf("需要存款的客户人数:%d\n",ndn);
printf("需要取款的客户人数:%d\n",nwn);
printf("成功办理存款的客户人数:%d\n",sdn);
printf("成功办理取款的客户人数:%d\n",swn);
printf("存款成功办理率:%f\n",float(sdn*100)/ndn);
printf("取款成功办理率:%f\n",float(swn*100)/nwn);
printf("客户逗留平均时间为:%f\n",float(totalTime)/counter);
printf("银行当前余额:%d\n",total);
printf("请按任意键退出!\n");
break;
}
if(n==0) printf("请按任意键退出!\n");
end:getch();
24
离到
return 0;
}
7.设计心得体会
刚开始的时候对课程设计还是挺害怕的,而且也不知道该从何处下手,总以为我们还没有具备完成的实力。虽然平时那些作业系统中的题目都能完成,但对于课程设计还是没有多少把握。经过一段时间的努力和奋斗,认认真真把教材又看了一遍,结合同学们之间互相的思想交流,我最终把解题思路确定了。然后在写代码及调试的过程中,虽然遇到了很多的困难和挫折,但我没有放弃,通过同学的帮助和指点,我把问题一个一个改正过来了,最终完成了。本课程设计主要用了队列和静态链表的知识,还有一些随机产生数的函数。这次实验,使我对栈和队列,静态链表的理解更全面了,也让我摸索出了学习数据结构的方法正确理解,多做练习!这次实验不仅让我明白了编程一定要多练才会熟悉,才能理解的正确,理解的透彻,更让我懂得了团队合作,互帮互助的重要性,培养了我的团队精神。
25