银行业务模拟系统

-严蔚敏数据结构-银行业务模拟系统的实现

1.需求分析
1.1输入的形式
输入的元素为整型类型;
输入的银行初始存款必须大于0;
输入的银行营业时间必须大于0且必须小于1440(一天);
输入的最大到达时间间隔必须大于0且必须小于银行营业时间;
输入的最小到达时间间隔必须大于0且必须小于最大到达时间间隔;
输入的最大处理时间必须大于0且必须小于银行营业时间;
输入的最小处理时间必须大于0且必须小于最大处理时间;
输入的交易额的最大上线必须大于0且必须小于银行初始存款且必须小于50000;
1.2输出的形式
输出的形式为以列表的形式输出事件处理序列;
并在列表输出完后输出需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。
1.3程序功能
实现银行业务的事件驱动模拟系统,通过模拟方法求出客户在银行内逗留的平均时间。
1.4测试
测试数据由程序用户手动输入,此处对于正确输入和错误输入给出样例。
(1)错误的输入
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
(2)正确的输入
这里写图片描述
(3)对应的输出结果
这里写图片描述
2.概要设计
2.1数据类型
本设计中用到的数据结构ADT定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ADT Queue{
数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n, n≥0 }
数据关系:R1={ <ai-1, ai>|ai-1, ai∈D, i=2,...,n }
基本操作:
void InitQueue(Queue &Q);
操作结果:构造空队列Q
CustNode *Queuefront(Queue &Q);
初始条件:队列Q存在
操作结果:返回队首元素
CustNode *Queuerear(Queue &Q);
初始条件:队列Q存在
操作结果:返回队尾元素
void EnQueue(Queue &Q,int e);
初始条件:队列Q存在
操作结果:插入元素e为Q的新的队尾元素。
void DeQueue(Queue &Q);
初始条件:队列Q存在
操作结果:删除Q的队头元素。
}ADT Queue

2.2主程序的流程
主程序先是让外部进行测试数据输入,待测试数据输入完后,执行银行业务模拟系统,产生需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。

2.3程序模块说明
这里写图片描述

3.详细设计
3.1头文件声明
为了增强代码可读性,使用头文件来记录各类结构体的声明以及常用变量的定义

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
#ifndef _Bank_H_
#define _Bank_H_
#include <string>
using namespace std;
/*客户结点类型*/
struct CustNode{
int num; //客户号
string Type; //到达或离开
int BeginTime; //到达时间
int EndTime; //离开时间
int Amount; //正数为存款,负数为取款
CustNode *next; //指针域
};
Struct Client{
Int arrivertime; //到达时间
Int durtime; //逗留时间
Int amount; //办理业务金额
Client *next; //指针域
};
Client pool[MaxNumber];
/*等待队列类型*/
struct Queue{
CustNode *front; //队列头指针
CustNode *rear; //队列尾指针
}Queue;
/*常用变量定义*/
int BankAmount; //初始时银行现存资金总额
int CloseTime; //营业结束时间
int ClientArriveMaxTime; //两个到达事件之间的间隔上限
int ClientArriveMinTime; //两个到达事件之间的间隔下限
int DealMaxTime; //客户之间交易的时间上限
int DealMinTime; //客户之间交易的时间下限
int MaxAmount; //交易额上限
int NeedIn=0; //需要存款的人数
int NeedOut=0; //需要取款的人数
int SuccessIn=0; //成功存款的人数
int SuccessOut=0; //成功取款的人数
int CurrentTime=0; //当前时间
int BankAmountTime=0; //客户逗留总时间
int counter=0; //客户总数
int number=1; //初始客户序列号
bool state=1; //用于判断是否有窗口在处理
int DealTime=0; //交易时间
int MaxTime=0; //最大到达时间
Queue Event; //事件队列
Queue Q1; //队列一
Queue Q2; //队列二
#endif
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
3.2选做算法
3.2.1动态分配函数
/*出栈,将栈顶元素的下标返回*/
伪码表示:
Begin
Client *p<-栈顶指针
e的arrivetime<-栈顶元素的arrivertime
e的durtime<-栈顶元素的durtime
e的amount<-栈顶元素的amount
栈顶指针指向下一元素
End
代码表示:
void myMalloc(Stack &S,Client &e){
Client *p=S.top;
e.arrivetime=(*S.top).arrivetime;
e.durtime=(*S.top).durtime;
e.amount=(*S.top).amount;
p->next=p->next->next;
S.top++;
p=p->next;
}
3.2.2归还函数
/*把该分量入栈*/
伪码表示:
Begin
Client *p<-栈顶指针
栈底元素的arrivertimee<-e的arrivetime
栈底元素的durtime<-e的durtime
栈底元素的amount<-e的amount
栈底指针指向下一元素
End
代码表示:
void myFree(Stack &S,Client e){
Client *p=S.rear;
(*S.rear).arrivertime=e.arrivetime;
(*S.rear).durtime=e.durtime;
(*S.rear).amount=e.amount;
p->next=p->next->next;
S.rear++;
p=p->next;
}
3.3函数算法
3.3.1创建队列
/*初始化操作,建立一个空队列*/
伪码表示:
Begin
分配存储空间给头结点和尾结点
IF头结点内存分配失败
EXIT
头结点的指针域<-空
End
代码表示:
void InitQueue(Queue &Q){
Q.front=Q.rear=(CustNode*)malloc(sizeof(CustNode));
if(!(Q.front))
exit(1);
Q.front->next=0;
}
3.3.2入队列
/*插入元素e为队列Q的新的队尾元素*/
伪码表示:
Begin
分配存储空间给结点p
结点p的金额置<-e
结点p的指针域<-空
IF队列<-空
Begin
头指针<-p
尾指针<-p
End
ELSE
Begin
头指针next域<-p
尾指针<-尾指针next域
End
End
代码表示:
void EnQueue(Queue &Q,int e){
CustNode* p=new CustNode;
p->Amount=e;
p->next=NULL;
if(Q.front==NULL){
//队列为空,初始化
Q.front=p;
Q.rear=p;
}
else{
//队列不为空,插入结点p
Q.rear->next=p;
Q.rear=Q.rear->next;
}
}
3.3.3出队列
/*使p中的第一个元素出队列*/
伪码表示:
Begin
p<-头指针
IF p的next域<-空
Begin
头指针<-空
尾指针<-空
End
ELSE
头指针<-头指针的next域
DELETE p
End
代码表示:
void DeQueue(Queue &Q){
CustNode *p;
p=Q.front;
if(Q.front->next==NULL) //队列只有一个元素
Q.front=Q.rear=NULL;
else //调整队列头指针
Q.front=Q.front->next;
delete p;
}
3.3.4取队首
/*返回队首元素*/
伪码表示:
Begin
Return 队首元素
End
代码表示:
CustNode *Queuefront(Queue &Q){
return Q.front;
}
3.3.5取队尾
/*返回队尾元素*/
伪码表示:
Begin
Return 队尾元素
End
代码表示:
CustNode *Queuerear(Queue &Q){
return Q.rear;
}
3.3.6处理客户到达事件
/*随机产生顾客,进入队列一产生到达事件 进入事件队列*/
伪码表示:
Begin
调用EnQueue(Q1,随机数)
Q1尾结点的BeginTime<-CurrentTime
Q1尾结点的num<-number
EnQueue(Event,尾结点的金额)
Event尾结点的BeginTime<-CurrentTime
Event尾结点的Type<-到达
Event尾结点的num<-number
number<-number+1
End
代码表示:
void ClientArrive(){
EnQueue(Q1,(rand()%(2*MaxAmount)-MaxAmount)); //随机产生顾客加入第一队列
Queuerear(Q1)->BeginTime=CurrentTime; //当前时间为客户的到达时间
Queuerear(Q1)->num=number; //客户号为客户序列号
EnQueue(Event,(Queuerear(Q1)->Amount)); //将产生事件加入事件队列
Queuerear(Event)->BeginTime=CurrentTime;
Queuerear(Event)->Type="到达";
Queuerear(Event)->num=number;
number++;
}
3.3.7存款
/*对客户存款事件进行处理*/
伪码表示:
Begin
BankAmount<-BankAmount+Q1头结点的Amount
调用EnQueue(Event,Q1头结点的Amount)
Event尾结点的Type<-离开
Event尾结点的num<-Q1头结点的num
Event尾结点的EndTime<-Q1头结点的BeginTime+随机处理时间
counter<-counter+1
BankAmountTime<-BankAmountTime+Event尾结点的EndTime-Q1头结点的BeginTime
调用DeQueue(Q1)
DealTime<-Event尾结点的EndTime
state<-0
End
代码表示:
void InAmount(){
BankAmount+=Queuefront(Q1)->Amount; //更新资金总额
EnQueue(Event,Queuefront(Q1)->Amount); //加入事件队列
Queuerear(Event)->Type="离开";
Queuerear(Event)->num=Queuefront(Q1)->num;
//离开时间为到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间 Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime+rand()%(DealMaxTime-DealMinTime +1)+DealMinTime);
counter++; //更新客户总数
BankAmountTime+=(Queuerear(Event)->EndTime-Queuefront(Q1)->BeginTime);
//更新逗留时间
DeQueue(Q1); //删除第一队列第一个业务
DealTime=Queuerear(Event)->EndTime; //交易时间为客户的离开时间
state=0; //窗口没有交易需要处理
}
3.3.8取款或借款
/*对客户取款或借款事件进行处理*/
伪码表示:
Begin
IF -Q1头结点的Amount>BankAmount
Begin
调用EnQueue(Q2,Q1头结点的Amount)
Q2尾结点的BeginTime<-Q1头结点的BeginTime
Q2尾结点的num<-Q1头结点的num
调用DeQueue(Q1)
End
ELSE
Begin
BankAmount<-BankAmount+Q1尾结点的Amount
调用EnQueue(Event,Q1头结点的Amount)
Event尾结点的Type<-离开
Event尾结点的num<-Q1头结点的num
Event尾结点的EndTime<-Q1头结点的BeginTime+随机处理时间
DealTime<-Event尾结点的EndTime
counter<-counter+1
BankAmountTime<-Event尾结点的EndTime-Q1尾结点的BeginTime
调用DeQueue(Q1)
State<-0
End
End
代码表示:
void OutAmount(){
if((-Q1.front->Amount)>BankAmount){
//资金短缺 加入第二队列
EnQueue(Q2,Queuefront(Q1)->Amount);
Queuerear(Q2)->BeginTime=Queuefront(Q1)->BeginTime;
Queuerear(Q2)->num=Queuefront(Q1)->num;
DeQueue(Q1);
}
else{
BankAmount+=Queuerear(Q1)->Amount; //更新资金总额
EnQueue(Event,Queuefront(Q1)->Amount); //加入事件队列
Queuerear(Event)->Type="离开";
Queuerear(Event)->num=Queuefront(Q1)->num;
//客户的离开时间为客户的到达时间加上随机产生的介于最大处理时间和最小处理时间的处理时间
Queuerear(Event)->EndTime=(Queuefront(Q1)->BeginTime +rand()%(DealMaxTime-DealMinTime +1)+DealMinTime);
Queuerear(Event)->BeginTime=0;
DealTime=Queuerear(Event)->EndTime; //交易时间为客户的离开时间
counter++; //更新客户总数
BankAmountTime+=(Queuerear(Event)->EndTime-Queuerear(Q1)->BeginTime);
//更新逗留时间
DeQueue(Q1); //删除第一队列第一个业务
state=0; //窗口没有交易需要处理
}
}
3.3.9检查队列Q2
/*顺序检查队列Q2中是否有可以处理的事件元素*/
伪码表示:
Begin
sign<-Q头结点
CustNode *temp
While Q头结点为空
Begin
IF -Q头结点的Amount<m
Begin
IF Q为空
Begin
temp<-Q头结点
Q头结点<-空
Q尾结点<-空
Return temp
End
ELSE
Begin
temp<-Q头结点
Q头结点<-Q头结点的next域
Return temp
End
End
ELSE
Begin
IF Q不为空
Begin
Q尾结点的next域<-Q头结点
Q尾结点<-Q尾结点的next域
Q头结点<-Q头结点的next域
Q尾结点的next域<-空
End
End
IF Q头结点等于sign
Return 空
End
Return 空
End
代码表示:
CustNode *SearchQ2(Queue &Q,int m){
CustNode *sign=Q.front; //标记头节点
CustNode *temp;
while(Q.front!=NULL){
if((-(Q.front->Amount))<m){ //队首元素可以处理
if(Q.front==Q.rear){
temp=Q.front;
Q.front=Q.rear=NULL;
return temp;
}
else{ //队首元素出列
temp=Q.front;
Q.front=Q.front->next; // 首节点后移一位,返回原首节点
return temp;
}
}
else{ //队首元首不能被处理
if(Q.front==Q.rear){
}
else{ //首节点移到队列尾部
Q.rear->next=Q.front;
Q.rear=Q.rear->next;
Q.front=Q.front->next;
Q.rear->next=NULL;
}
}
if(Q.front==sign) //队列循环一周时停止
return NULL;
}
return NULL;
}
3.3.10处理队列Q2
/*对于队列Q2中可以处理的事件元素进行处理*/
伪码表示:
Begin
CustNode* temped
int RandomTemp
While temped<-调用SearchQ2(Q2,BankAmount)并且temped不为空
Begin
BankAmount<-temped的Amount+BankAmount
EnQueue(Event,temped的Amount
Event尾结点的Type<-离开
Event尾结点的num<-temped的num
RandomTemp<-随机处理时间
Event尾结点的EndTime<-CurrentTime+RandomTemp
DealTime<-DealTime+RandomTemp
counter<-counter+1
BankAmountTime<-Event尾结点的EndTime-temped的BeginTime+BankAmount
删除 temped
temped<-空
End
state<-0
End
代码表示:
void DealQ2(){
CustNode* temped;
int randomTemp;
while((temped=SearchQ2(Q2,BankAmount))&&temped!=NULL){ //查找可处理取款
BankAmount+=temped->Amount; //更新资金总额
EnQueue(Event,temped->Amount); //加入事件队列
Queuerear(Event)->Type="离开";
Queuerear(Event)->num=temped->num;
RandomTemp=rand()%(DealMaxTime-DealMinTime +1)+DealMinTime;
//处理时间为随机产生的介于最大处理时间和最小处理时间之间的处理时间
Queuerear(Event)->EndTime=CurrentTime+randomTemp ;
//客户离开时间为当前时间加上处理时间
DealTime+=randomTemp; //更新交易时间
counter++; //更新客户总数
BankAmountTime+=(Queuerear(Event)->EndTime-temped->BeginTime);
//更新逗留时间
delete temped; //删除节点
temped = NULL;
}
state = 0;
}
3.3.11银行业务模拟系统界面
/*银行业务模拟程序的界面*/
伪码表示:
Begin
输出 ========================================================================= 换行
输出 ========================================================================= 换行
输出 Simulation of The Bank business
换行
输出 -------------------------------------------------------------------------
换行
输出 ---------------------------------
换行
输出 Number: 3116004979
输出 CLASS :16网络二班
输出 NAME : 詹泽霖
输出 ========================================================================= 换行
输出 *************************************************************************
换行
输出 ************************************************************************* 换行
输出 ******************* *********************** 换行
输出 ******************* 0.退出 1.进入模拟系统 ***********************
换行
输出 ******************* *********************** 换行
输出 *************************************************************************
换行
输出 *************************************************************************
换行
输出 ************************ 请选择服务 *************************** 换行
输出 ========================================================================= 换行
End
代码表示:
void BankOutLook(){
printf(" ========================================================================= \n");
printf(" ========================================================================= \n");
printf(" Simulation of The Bank business \n");
printf(" ------------------------------------------------------------------------- \n\n");
printf(" --------------------------------- \n");
printf(" Number: 3116004979 \n");
printf(" CLASS :16网络二班 \n");
printf(" NAME : 詹泽霖 \n");
printf(" --------------------------------- \n");
printf(" ========================================================================= \n");
printf(" ************************************************************************* \n");
printf(" ************************************************************************* \n");
printf(" ******************* ************** \n");
printf(" ******************* 0.退出 1.进入模拟系统 *************** \n");
printf(" ******************* ************** \n");
printf(" ************************************************************************* \n");
printf(" ************************************************************************* \n");
printf(" ************************ 请选择服务 ********************* \n");
printf(" ========================================================================= \n");
printf(" 请输入选择的操作对应编号:");
}
3.4主程序
通过对以上定义过的函数接口的调用,利用主函数来构建一个银行模拟系统,以列表的形式输出事件处理序列;
并在列表输出完后输出需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。
3.4.1伪码表示
Begin
调整界面为黑字白背景
调用BankOutLook()
输入操作编号
While 操作编号等于1
Begin
初始化随机函数
输出 请输入银行的初始存款
输入 银行初始存款
IF 银行初始存款<0
Begin
输出 输入错误,重新输入
输入 银行初始存款
IF 银行初始存款<0
Begin
输出 输入错误,重新输入
输入 银行初始存款
IF银行初始存款<0
输出 三次输入错误,退出
End
End
输出 请输入银行的营业时间
输入 银行营业时间
IF 银行营业时间<0或者>1440
Begin
输出 输入错误,请重新输入
输入 银行营业时间
IF 银行营业时间<0或者>1440
Begin
输出 输入错误,请重新输入
输入 银行营业时间
IF 银行营业时间<0或者>1440
输出 三次输入错误,退出程序
End
End
输出 请输入最大到达时间间隔
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大到达时间间隔
IF 最大到达时间间隔>银行营业时间
输出 三次输入错误,退出程序
End
End
输出 请输入最小到达时间间隔
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
Begin
输出 输入错误,请重新输入
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
Begin
输出 输入错误,请重新输入
输入 最小到达时间间隔
IF 最小到达时间间隔>最大到达时间间隔
输出 三次输入错误,退出程序
End
End
输出 请输入最大交易时间
输入 最大交易时间
IF 最大交易时间>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大交易时间
IF 最大交易时间>银行营业时间
Begin
输出 输入错误,请重新输入
输入 最大交易时间
IF 最大交易时间>银行营业时间
输出 三次输入错误,退出程序
End
End
输出 请输入最小交易时间
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
输出 三次输入错误,退出程序
End
End
输出 请输入最小交易时间
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最小交易时间>最大交易时间
输出 三次输入错误,退出程序
End
End
输出 请输入最大交易额
输入 最大交易额
IF 最大交易额>银行初始金额
Begin
输出 输入错误,请重新输入
输入 最小交易时间
IF 最大交易额>银行初始金额
Begin
输出 输入错误,请重新输入
输入 最大交易额
IF 最大交易额>银行初始金额
输出 三次输入错误,退出程序
End
End
MaxTime<-MaxTime+随机到达间隔
While CurrentTime<CloseTime
Begin
CurrentTime<-CurrentTime+1
If DealTime<CurrentTime
DealTime<-CurrentTime
If DealTime等于CurrentTime
State<-1
IF CurrentTime等于MaxTime)
Begin
调用ClientArrive()
MaxTime<-MaxTime+随机到达间隔+ClientArriveMinTime
End
IF state等于1&&Q1头指针不等于NULL
Begin
IF Q1头结点的Amount大于等于 0
Begin
调用InAmount()
调用DealQ2()
NeedIn<-NeedIn+1
End
ElSe
Begin
调用InAmount()
NeedIn<-NeedIn+1
End
End
End
输出 客户序列 换列 事件类型 换列 处理金额 换行
While Event头结点不为空
Begin
IF Event头结点的Type等于 "离开"
Begin
输出 换列 Event头结点的num 换列 离开 Event头结点的EndTime 换列 Event头结点的Amount 换行
IF Event头结点的Amount大于等于0
t1<-t1+1
Else
t3<-t3+1
End
Else
Begin
输出 换列 Event头结点的num 换列 到达 Event头结点的EndTime 换列 Event头结点的Amount 换行
IF Event头结点的Amount大于等于0
t2<-t2+1
Else
t4<-t4+1
SuccessIn<-NeedIn-(t2-t1)
SuccessOut<-NeedOut-(t4-t3)
调用DeQueue(Event)
End
While Q1的头结点等于NULL
Begin BankAmountTime<-BankAmountTime+(CloseTime-Q1头结点的BeginTime)
counter<-counter+1;
调用DeQueue(Q1);
End
换行
输出 需要存款的客户人数
输出 需要取款的客户人数
输出 成功办理存款的客户人数
输出 成功办理取款的客户人数
输出 存款成功办理率
输出 取款成功办理率
输出 客户进入系统平均时间
输出 银行当前余额
End
If 操作数等于0
退出模拟系统
Return 0
End
3.4.2代码表示
int main(){
system("color 70");
BankOutLook();
int n,t1=0,t2=0,t3=0,t4=0,m=0;
scanf("%d",&n);
while(n==1){
srand(time(NULL)); //初始化随机函数
printf(" 请输入银行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<0){
printf(" 输入错误!初始存款不能小于0!请再次输入!\n");
printf(" 请输入银行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<0){
printf(" 输入错误!初始存款不能小于0!请最后一次输入!\n");
printf(" 请输入银行的初始存款:");
scanf("%d",&BankAmount);
if(BankAmount<0){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
printf(" 请输入银行的营业时间:");
scanf("%d",&CloseTime);
if(CloseTime>=1440){
printf(" 输入错误!一天的营业时间不能超过1440分钟(24个小时)!请再次输入!\n");
printf(" 请输入银行的营业时间:");
scanf("%d",&CloseTime);
if(CloseTime>=1440){
printf(" 输入错误!一天的营业时间不能超过1440分钟(24个小时)!请最后一次输入!\n");
printf(" 请输入银行的营业时间:");
scanf("%d",&CloseTime);
if(CloseTime>=1440){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
printf(" 请输入最大到达时间间隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 输入错误!最大到达时间间隔必须小于营业时间!请再次输入!\n");
printf(" 请输入最大到达时间间隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 输入错误!最大到达时间间隔必须小于营业时间!请最后一次输入!\n");
printf(" 请输入最大到达时间间隔:");
scanf("%d",&ClientArriveMaxTime);
if(ClientArriveMaxTime>CloseTime){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
printf(" 请输入最小到达时间间隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请再次输入!\n");
printf(" 请输入最小到达时间间隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 输入错误!最小到达时间间隔必须介于零和最大到达时间之间!请最后一次输入!\n");
printf(" 请输入最小到达时间间隔:");
scanf("%d",&ClientArriveMinTime);
if(ClientArriveMinTime<=0||ClientArriveMinTime>=ClientArriveMaxTime){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
printf(" 请按任意键退出!\n");
goto end;
}
}
}
printf(" 请输入最大的处理时间:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 输入错误!最大处理时间必须小于营业时间!请再次输入!\n");
printf(" 请输入最大的处理时间:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 输入错误!最大处理时间必须小于营业时间!请最后一次输入!\n");
printf(" 请输入最大的处理时间:");
scanf("%d",&DealMaxTime);
if(DealMaxTime>CloseTime){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
printf(" 请输入最小的处理时间:");
scanf("%d",&DealMinTime);
if(DealMinTime<=0||DealMinTime>=DealMaxTime){
printf(" 输入错误!最小处理时间必须介于零和最大处理时间之间!请再次输入!\n");
printf(" 请输入最小的处理时间:");
scanf("%d",&DealMinTime);
if(DealMinTime<=0||DealMinTime>=DealMaxTime){
printf(" 输入错误!最小处理时间必须介于零和最大处理时间之间!请最后一次输入!\n");
printf(" 请输入最小的处理时间:");
scanf("%d",&DealMinTime);
if(DealMinTime<=0 || DealMinTime>=DealMaxTime){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
printf(" 请输入交易额的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>50000){
printf(" 输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请再次输入!\n");
printf(" 请输入交易额的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>50000){
printf(" 输入错误!超出本银行的服务范围!最大交易额应低于银行开始营业时的资金总额且小于50000!请最后一次输入!\n");
printf(" 请输入交易额的最大上限:");
scanf("%d",&MaxAmount);
if(MaxAmount>=BankAmount||MaxAmount>50000){
printf(" 三次输入都错误!请按任意键退出!\n");
getch();
goto end;
}
}
}
MaxTime +=rand()%(ClientArriveMaxTime-ClientArriveMinTime+1)+ClientArriveMinTime;
//随机生成介于最大到达时间间隔和最小到达时间间隔之间的首次到达时间
while(CurrentTime<CloseTime){ //当前时间小于营业时间
CurrentTime++;
if(DealTime<CurrentTime)
DealTime=CurrentTime ;
if(DealTime==CurrentTime) //有窗口在处理交易
state=1;
if(CurrentTime==MaxTime){ //到达事件
ClientArrive();
//随机生成介于最大到达时间间隔和最小到达时间间隔之间的到达时间
MaxTime+=rand()%(ClientArriveMaxTime-ClientArriveMinTime+1)+ClientArriveMinTime;
}
if(state==1&&Q1.front!=NULL){
if(Q1.front->Amount>= 0){
InAmount(); //调用存款函数
DealQ2(); //调用搜索处理函数
NeedIn++;
}
else{
InAmount(); //调用取款函数
NeedOut++;
}
}
}
printf(" 客户序列\t 事件类型 时间 处理金额\n");
while(Event.front!=NULL){ //清除事件队列
if(Event.front->Type=="离开"){
printf("\t%d\t\t离开\t\t%d\t\t%d\n",Event.front->num, Event.front->EndTime,Event.front->Amount);
if(Event.front->Amount>=0) //成功存款人数
t1++;
else //成功取款人数
t3++;
}
else{
printf("\t%d\t\t到达\t\t%d\t\t%d\n",Event.front->num, Event.front->BeginTime,Event.front->Amount);
if(Event.front->Amount>=0) //需要存款人数
t2++;
else //需要取款人数
t4++;
}
SuccessIn=NeedIn-(t2-t1);
SuccessOut=NeedOut-(t4-t3);
DeQueue(Event);
}
while(Q1.front!=NULL){
//更新结束时第一队列中未处理的客户
BankAmountTime+=(CloseTime-Q1.front->BeginTime);
counter++;
DeQueue(Q1);
}
printf("\n");
printf(" 需要存款的客户人数:%d\n",NeedIn);
printf(" 需要取款的客户人数:%d\n",NeedOut);
printf(" 成功办理存款的客户人数:%d\n",SuccessIn);
printf(" 成功办理取款的客户人数:%d\n",SuccessOut);
printf(" 存款成功办理率:%f\n",float(SuccessIn*100)/NeedIn);
printf(" 取款成功办理率:%f\n",float(SuccessOut*100)/NeedOut);
printf(" 客户逗留平均时间为:%f\n",float(BankAmountTime)/counter);
printf(" 银行当前余额:%d\n",BankAmount);
printf(" 请按任意键退出!\n");
break;
}
if(n==0)
printf("请按任意键退出!\n");
end:getch();
return 0;
}

3.5函数调用关系及程序流程
以下为程序的大致流程图:
这里写图片描述
函数调用关系图如下:
这里写图片描述

4.调试分析
4.1调试中遇到的问题
调试中遇到的问题不是很多,但遇到的问题在一定程度上让我更加的了解整个程序的运作机理,对于理解数据结构也有很大的帮助。
主要的问题在于一开始的时候实现检查Q2队列的接口时,在进行检查后,未再让经过检查却不满足处理的元素重新进入Q2队列,导致最后的元素缺少。经过调试发现了这个问题,对代码进行修正,最终解决了问题。
4.2算法分析
这里写图片描述

4.3经验体会
通过这次的课程设计的编写,学会了在多种数据结构之间进行巧妙的结合运用。同时,对于用到的多种数据结构也有了更多的了解。
在测试功能的时候一定要注意选取的测试数据的正确性和实用性。
5.用户使用说明
在进入银行业务模拟界面时,选择操作编号,0-退出系统,1-进入模拟系统.
进入模拟系统后,输入的银行初始存款必须大于0;
输入的银行营业时间必须大于0且必须小于1440(一天);
输入的最大到达时间间隔必须大于0且必须小于银行营业时间;
输入的最小到达时间间隔必须大于0且必须小于最大到达时间间隔;
输入的最大处理时间必须大于0且必须小于银行营业时间;
输入的最小处理时间必须大于0且必须小于最大处理时间;
输入的交易额的最大上线必须大于0且必须小于银行初始存款且必须小于50000;
若输入有误会进行提示,三次错误后退出模拟系统。若输入无误,则开始进行输出,输出事件处理的列表信息,以及需要存款的客户人数,需要取款的客户人数,成功办理存款的客户人数,成功办理取款的客户人数,存款成功办理率,取款成功办理率,客户逗留平均时间,银行当前余额等信息。

6.测试结果
6.1输出测试1
输入较大的银行初始存款,输入较大的到达时间间隔和较大的处理时间,较小的交易额上限
这里写图片描述
由于到达时间间隔和处理时间输入较大,测试数据会比较少,相对于来说,求得的银行业务模拟的客户平均用时等信息可能就没有那么的精确
这里写图片描述
6.2输出测试2

输入较大的银行初始存款,输入较小的到达时间间隔范围,较小的交易额上限
这里写图片描述
在较小的到达时间间隔和处理时间的输入下,会得到比前一种情况更多的测试数据输出,在此情况下,样本的容量足够大,对于客户平均用时等信息的统计就可能会更加的精确一些

这里写图片描述
这里写图片描述
这里写图片描述
6.3输出测试3
输入较小的银行初始存款,较大的处理时间和较大的时间间隔,较大的交易金额上限。
这里写图片描述
在这样的输出下,对于客户平均用时的影响比较大,且只能产生少量的数据。
这里写图片描述
7.参考文献

参考文献
[1] 张小艳,龚尚福编著. 数据结构与算法. 徐州:中国矿业大学出版社,2007
[2] 严蔚敏,吴伟民编著. 数据结构(C语言版). 北京: 清华大学出版社,1997
[3] 谭浩强编著. C程序设计(第三版). 北京: 清华大学出版社,2005

Thanks for your reward!