📄 bank.cpp
字号:
// 银行业务模拟,统计最近10个客户的平均停留时间,按平均队长调整营业窗口数
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <alloc.h>
#include <dos.h>
typedef struct {
unsigned int occurtime ; // 本事件发生时刻
int ntype ; // 本事件类型, 0到达事件, 1~ 4各窗口离开事件
}event,elemtype; // 事件链表结点中的数据元素类型
typedef struct event0{ // 事件链表结点
elemtype data;
struct event0 *next;
}event0,*eventlist;
typedef struct {
unsigned int arrivaltime ; // 该客户到达时刻
int duration,num ; // 该客户处理事务耗时
}QElemType; // 客户队列链表结点中的数据元素类型
typedef struct QT{ // 窗口队列链表结点
QElemType t;
struct QT *next;
} *linkqueue;
eventlist ev ; // 事件(链)表头指针
event en ; // 事件变量
linkqueue q[7] ; // 4个 客户 队列(链环,用尾指针表示)
QElemType customer; // 客户记录变量
long totaltime; // 累计最近10个客户逗留时间
unsigned int i,m=7,customernum,num0=0, // m-1是营业窗口数,离开客户数,到达客户编号
durtime0=240, intertime0=60, // 平均处理时间,平均到达间隔(秒)
closetime,sum[10],s1=0; // 终止时间,逗留时间累计区,指针
float l0; // 平均队列长度
void initqueu(linkqueue &r){ // 初始化队列,尾指针表示的链环。
r=(linkqueue)malloc(sizeof(QT));
r->next=r; r->t.duration=0; // 头结点中(t.duration)记队列长度。
gotoxy(1,4*i-2); printf("\n\n");
}
void enqueue(linkqueue &r,int arrt,int durt,int num){ // 入队
linkqueue r0;
r0=(linkqueue)malloc(sizeof(QT));
r0->t.arrivaltime=arrt; r0->t.duration=durt; r0->t.num=num;
r0->next=r->next; r->next=r0; r=r0; // 维护尾指针
r->next->t.duration++; // 维护队长度。
}
void delqueue(linkqueue &r,QElemType &cust){
linkqueue s;
s=r->next->next; r->next->next=s->next;
cust=s->t; r->next->t.duration--; // 维护队长度。
if(s==r) r=r->next; // 维护尾指针
free(s);
}
void gethead(linkqueue r,QElemType &cust){ // 取队头元素
cust=r->next->next->t;
}
queulength(linkqueue r){ // 队列长度
return(r->next->t.duration);
}
void InitList(eventlist &h){ // 事件表初始化,链环
h=(eventlist)malloc(sizeof(event0));
h->next=h;
}
void oderinsert(eventlist h,int time,int ty){ // 插入事件表,时间有序
eventlist p,q;
h->data.occurtime=time+1; p=h; // 利用监视哨查找算法
while(time>=p->next->data.occurtime) p=p->next;
q=(eventlist)malloc(sizeof(event0));
q->data.occurtime=time; q->data.ntype=ty;
q->next=p->next; p->next=q;
}
void delfirst(eventlist h,event &en){ // 截取事件表第一元素
eventlist p;
p=h->next; h->next=p->next; en=p->data; free(p);
}
void openforday() { // 系统初始化
randomize();
totaltime = 0; customernum = 0; InitList(ev); // 初始化事件队列
oderinsert(ev,0,0); // 设定第一客户到达事件插入事件表
for ( i=1; i<m; ++ i) initqueu(q[i]); // 客户队列置空
for ( i=0; i<10; ++ i) sum[i]=0; // 初始化逗留时间累计缓冲区
}
void random2(int &durtime,int &intertime){ // 生成随机的业务时间和到达间隔
durtime=2*durtime0/3; durtime=durtime+random(durtime);
intertime=random(2*intertime0);
}
minimum(linkqueue *q){ // 寻找最短队,统计平均队列长
int i,j;
i=j=1; l0=0;
while(i<m){
if(q[i]->next->t.duration<q[j]->next->t.duration) j=i;
l0 += q[i]->next->t.duration; i++;
} l0 /= m-1; return j;
}
void customerarrived( ) { // 处理客户到达事件,en.ntype 为 0
int t,durtime, intertime;
random2(durtime, intertime); num0++;
t = en.occurtime + intertime ; // 下一客户到达时刻
if(t<closetime) oderinsert(ev,t,0); // 未到下班时间, 插入
i = minimum(q);
enqueue(q[i],en.occurtime,durtime,num0); // 插入短队
if(queulength(q[i]) == 1) // 若该客户即队头则生成下一离开事件
oderinsert(ev, en.occurtime+durtime, i);
}
void customerdeparture( ) { // 处理离开事件,en.ntype > 0
++customernum;
i = en.ntype ; delqueue(q[i], customer);
totaltime -= sum[s1];
sum[s1]=en.occurtime - customer.arrivaltime; // 累计逗留时间
totaltime += sum[s1++]; s1 %= 10;
if(l0>6&&m<7) m++; // 根据平均队长调整营业窗口数
if(l0<3&&m>2) m--;
if(q[i]->next!=q[i]) {
gethead(q[i], customer);
oderinsert(ev, en.occurtime + customer.duration, i);
} // 队非空则生成下一离开事件插入事件队列,
}
void display(){ // 显示当前(本次事件涉及的)队列,系统时间,平均间隔,离开客户数
linkqueue s;
unsigned int n;
gotoxy(3,4*i-1); clreol(); s=q[i]->next->next;
while(s!=q[i]->next){
printf("%c",s->t.num%26+65); s=s->next;
}
gotoxy(1,1);
printf("Sys_time %4d:%2d Aver_intertime(\x18/\x19):%4d Customers:%4d",
en.occurtime/60,en.occurtime%60,intertime0,customernum);
gotoxy(24,25); n=totaltime/10;
printf(" Aver_Stay_Time %5d:%2d Aver_Len %4.1f", n/60,n%60,l0);
delay(100); // 显示平均逗留时间和平均队列长度
}
void bank_simulation() { // 银行事务模拟
openforday(); // 初始化
while(ev->next!=ev) {
delfirst(ev, en); // 取链头事件赋 en
if(en.ntype == 0) customerarrived(); // 处理客户到达事件
else customerdeparture(); // 处理客户离开事件
display();
if(kbhit()){ // 处理热键
if(!getch()){
switch(getch()){
case 72: if(intertime0>10) intertime0--; break;
case 80: intertime0++;
defualt:
}
}
else break;
}
}
}
main(){
clrscr();
printf("\n\nPlease enter finished_time(<=1000 minute):");
do{
gotoxy(43,3);
scanf("%d",&closetime);
}while(closetime>1000||closetime<=0);
closetime *= 60;
bank_simulation(); return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -