银行排队系统仿真

问题描述

银行排队系统仿真:模拟一个银行排队系统一天的运行情况。

实验内容

  • 基本功能:模拟一个单队列、多窗口的银行排队系统一天的运行情况,随机生成顾客的到达时间和办理业务所需时间等数据。一天结束后,统计顾客的平均等待时间和窗口的平均占用率。

  • 可选做的高级功能:(1)改变顾客办理业务所需时间或银行的窗口数,观察顾客平均等待时间和窗口平均占用率如何变化;(2)假设每位顾客有一个容忍时间,等待超过容忍时间之后顾客将离开,统计顾客的离开率;(3)假设银行有两个队列,其中一个是VIP队列,另一个是普通队列,窗口服务的规则改为:若VIP队列不空,则优先服务VIP,否则服务普通顾客,统计VIP和普通顾客的平均等待时间有多大的差别。

源代码

下载源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<stdint.h>
typedef int ElemType;
enum is_vip_or_not{is_vip,not_vip};
typedef struct {
int arrival; // 客户到达银行的时间
int service_time; // 客户办理业务所需时间
is_vip_or_not _vip;
} customer;
enum status {idle, busy};
typedef struct {
status cur_status; // 窗口当前状态:忙or闲
int cur_start_time; // 当前状态开始的时间
int cur_customer; // 当前服务客户的编号(如果在忙)
} window;
typedef struct {
ElemType *elem; // 基地址
int queuesize; // 当前分配内存大小
int front, rear;
} SqQueue;
void EnQueue_sq(SqQueue &Q, ElemType e) {
Q.elem[Q.rear] = e; Q.rear = Q.rear+1;
}
bool DeQueue_sq(SqQueue &Q, ElemType *e) {
if (Q.front == Q.rear) return false;
*e = Q.elem[Q.front]; Q.front = Q.front+1;
return true;
}
int QueueLength_sq(SqQueue Q) {
return Q.rear - Q.front ;
}
void print_menu(void){
printf("====银行模拟系统====\n");
printf("1.简易银行模拟系统 2.普通银行模拟系统\n");
printf("3.退出系统\n");
}
void bank_simulation(int nc, customer *cust, int nw, window *win,int all_open_time) {
int t = 0;
int c, w;
int idw = nw;
int acc;
long int all_wait_time=0;
long int all_use_time=0;
printf("Bank open now\n" );
SqQueue Q;
Q.elem=(ElemType*)malloc( nc*sizeof(ElemType));
Q.queuesize=nc;
Q.front=0;
Q.rear=0;

for(acc=0;acc<nw;acc++)
win[acc].cur_status=idle;
// 所有窗口状态初始化为idle
while (t <= all_open_time || QueueLength_sq(Q) > 0 || idw < nw) {
if (t <= all_open_time)
for (c=0; c<nc; ++c)
if (cust[c].arrival == t) {
EnQueue_sq(Q, c);
printf("%d号客户于%d时间进入队列\n", c, t);
}
for (w=0; w<nw; w++)
if (win[w].cur_status == busy) {
c = win[w].cur_customer;
if ((t - win[w].cur_start_time) >= cust[c].service_time) {
win[w].cur_status = idle;
printf("%d号客户于%d时间在%d号窗口服务结束\n",c,t,w);
win[w].cur_start_time = t;
idw++;
}
}
for (w=nw-1; w>=0; w--) {
if (win[w].cur_status == idle && QueueLength_sq(Q) > 0) {
DeQueue_sq(Q, &c);
printf("%d号客户于%d时间在%d号窗口接受服务\n",c,t,w);
all_wait_time =all_wait_time - cust[c].arrival + t;
idw--;
win[w].cur_customer=c;
win[w].cur_status = busy; // 将窗口状态改为busy
win[w].cur_start_time = t;
all_use_time =all_use_time + cust[c].service_time;
}
}
t++;
}
printf("Bank close now\n");
printf("客户平均等待时间为:%f\n",((float)all_wait_time)/nc);
printf("窗口的平均占用率为:%f\n",((float)all_use_time)/(nw*t));
}
void bank_simulation_plus(int nc, customer *cust, int nw, window *win,int all_open_time,int max_stand_time,int number_of_vip) {
int t = 0;
int x = 0;
int c, w;
int idw = nw;
int acc;
long int all_wait_time=0;
long int all_use_time=0;
int number_of_leave=0;
long int all_vip_wait_time=0;
long int all_no_vip_wait_time=0;
printf("Bank open now\n" );
SqQueue Q;
Q.elem=(ElemType*)malloc( nc*sizeof(ElemType));
Q.queuesize=nc;
Q.front=0;
Q.rear=0;
SqQueue VIPQ;
VIPQ.elem=(ElemType*)malloc( nc*sizeof(ElemType));
VIPQ.queuesize=nc;
VIPQ.front=0;
VIPQ.rear=0;
for(acc=0;acc<nw;acc++)
win[acc].cur_status=idle;
// 所有窗口状态初始化为idle
while (t <= all_open_time || QueueLength_sq(Q) > 0 ||QueueLength_sq(VIPQ) > 0 || idw < nw) {
if (t <= all_open_time)
for (c=0; c<nc; ++c)
if (cust[c].arrival == t) {
if(cust[c]._vip==not_vip) {
EnQueue_sq(Q, c);
printf("%d号客户于%d时间进入队列\n", c, t);
}
else{
EnQueue_sq(VIPQ, c);
printf("%d号客户于%d时间进入VIP队列\n", c, t);
}
}
for (w=0; w<nw; w++)
if (win[w].cur_status == busy) {
c = win[w].cur_customer;
if ((t - win[w].cur_start_time) >= cust[c].service_time) {
win[w].cur_status = idle;
printf("%d号客户于%d时间在%d号窗口服务结束\n",c,t,w);
win[w].cur_start_time = t;
idw++;
}
}
for(x=Q.front;x<Q.rear;x++)
{
if(t-cust[Q.elem[x]].arrival>=max_stand_time) {
DeQueue_sq(Q, &Q.elem[x]);
printf("%d号客户等了%d分钟后离开了银行\n",Q.elem[x],max_stand_time);
number_of_leave++;
all_wait_time+=max_stand_time;
all_no_vip_wait_time+=max_stand_time;
}
}
for(x=VIPQ.front;x<VIPQ.rear;x++)
{
if(t-cust[VIPQ.elem[x]].arrival>=max_stand_time) {
DeQueue_sq(VIPQ, &VIPQ.elem[x]);
printf("%d号客户等了%d分钟后离开了银行\n",VIPQ.elem[x],max_stand_time);
number_of_leave++;
all_wait_time+=max_stand_time;
all_vip_wait_time+=max_stand_time;
}
}
for (w=nw-1; w>=0; w--) {
if (win[w].cur_status == idle && QueueLength_sq(VIPQ) > 0) {
DeQueue_sq(VIPQ, &c);
printf("%d号客户于%d时间在%d号窗口接受VIP服务\n",c,t,w);
all_wait_time =all_wait_time - cust[c].arrival + t;
all_vip_wait_time = all_vip_wait_time -cust[c].arrival +t;
idw--;
win[w].cur_customer=c;
win[w].cur_status = busy; // 将窗口状态改为busy
win[w].cur_start_time = t;
all_use_time =all_use_time + cust[c].service_time;
}
else if (win[w].cur_status == idle && QueueLength_sq(Q) > 0) {
DeQueue_sq(Q, &c);
printf("%d号客户于%d时间在%d号窗口接受服务\n",c,t,w);
all_wait_time =all_wait_time - cust[c].arrival + t;
all_no_vip_wait_time=all_no_vip_wait_time-cust[c].arrival + t;
idw--;
win[w].cur_customer = c;
win[w].cur_status = busy; // 将窗口状态改为busy
win[w].cur_start_time = t;
all_use_time =all_use_time + cust[c].service_time;
}
}
t++;
}
printf("Bank close now\n");
printf("客户平均等待时间为:%f\n",((float)all_wait_time)/nc);
printf("普通客户平均等待时间为:%f\n",((float)all_no_vip_wait_time)/(nc-number_of_vip));
printf("VIP客户平均等待时间为:%f\n",((float)all_vip_wait_time)/number_of_vip);
printf("窗口的平均占用率为:%f\n",((float)all_use_time)/(nw*t));
printf("顾客的离开率为:%f\n",((float)number_of_leave)/nc);
}
int get_number(void){
int i;
while(scanf("%d",&i)!=1||(i<1||i>3)){
printf("ERROR!请输入1~3的数字!请重新输入!\n");
while(getchar()!='\n') continue;
}
return i;
}
int main(){
customer cust[100000];
window win[1000];
int num_choice;
int i;
int all_open_time;
int customer_number;
int window_number;
int customer_min_time;
int customer_max_time;
int max_stand_time;
int number_of_vip;
print_menu();
while(1) {
num_choice = get_number();
switch (num_choice) {
case 1:
srand((unsigned) time(NULL));
printf("请输入银行开门时长(单位为分钟):");
scanf("%d", &all_open_time);
printf("请输入预估客户数量:");
scanf("%d", &customer_number);
printf("请输入客户办理业务所需最少时间:");
scanf("%d", &customer_min_time);
printf("请输入客户办理业务所需最多时间:");
scanf("%d", &customer_max_time);
for (i = 0; i < customer_number; i++) {
cust[i].arrival = (int) rand() % all_open_time;
cust[i].service_time = (int) (rand() % (customer_max_time - customer_min_time + 1) + customer_min_time);
}
printf("请输入开通窗口数量:");
scanf("%d", &window_number);
bank_simulation(customer_number, cust, window_number, win, all_open_time);
print_menu();
break;
case 2:
srand((unsigned) time(NULL));
printf("请输入银行开门时长(单位为分钟):");
scanf("%d", &all_open_time);
printf("请输入预估客户数量:");
scanf("%d", &customer_number);
printf("请输入客户办理业务所需最少时间:");
scanf("%d", &customer_min_time);
printf("请输入客户办理业务所需最多时间:");
scanf("%d", &customer_max_time);
printf("请输入客户最大容忍等待时间(若不需要请输入-1):");
scanf("%d",&max_stand_time);
if(max_stand_time<0)
max_stand_time=100*all_open_time;
printf("请输入VIP客户的数量:");
scanf("%d",&number_of_vip);
for (i = 0; i < customer_number; i++) {
cust[i].arrival = (int) rand() % all_open_time;
cust[i].service_time = (int) (rand() % (customer_max_time - customer_min_time + 1) + customer_min_time);
}
for(i=0;i<number_of_vip;i++){
cust[i]._vip=is_vip;
}
for(i=number_of_vip;i<customer_number;i++){
cust[i]._vip=not_vip;
}
printf("请输入开通窗口数量:");
scanf("%d", &window_number);
bank_simulation_plus(customer_number, cust, window_number, win, all_open_time,max_stand_time,number_of_vip);
print_menu();
break;
case 3:
printf("Bye\n");
exit(0);
}
}
}