离散事件模拟

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
/* by SonicRang */

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

using namespace std;

#define WINDOW 5 //定义服务窗口个数

/* 定义各窗口服务队列 */

typedef struct qnode
{
int arrivetime; //到达时刻
int duration; //处理时长
struct qnode *next;
}Qnode, *Queptr;


typedef struct
{
Qnode *front, *rear;
int length;
}LinkQueue;

/* 定义结束 */

/* 定义一天内所有事件链表 */
typedef struct enode
{
int occurTime, NType; //事件发生时刻,事件类型(0:未发生 非0:已完成)
struct enode *next;
}Enode, *Eptr;

typedef struct
{
Enode *front, *rear;
int eventNum; //事件数
}EventList;

/* 定义结束 */


/* 定义全局变量 */

EventList *eventlist; //事件链表
LinkQueue q[WINDOW + 1]; //窗口队列
Eptr pe, ev; //事件节点

int seed = 300;
int closetime; //银行工作时长
int totaltime; //总时间
int customerNum; //客流量

/* 定义结束 */



/* 插入客户事件到事件链表 */

void InsertEvent(EventList *eventlist, int Time, int Type)
{
Eptr p, q, location;
p = new Enode;
p->occurTime = Time;
p->NType = Type;
eventlist->eventNum++;
q = eventlist->front;
location = NULL;


while (q && (Time > q->occurTime)) //找到插入位置
{
location = q;
q = q->next;
}


if (location == NULL) //找到了空队列插入到队头
{
p->next = eventlist->front;
eventlist->front = p;
}
else //找到了非空队列插入到队尾
{
p->next = q;
location->next = p;
}


if (eventlist->eventNum == 1) //初始化队尾
{
eventlist->rear = p;
}
}

/* 插入完成 */



/* 删除事件链表中的事件 */
void DeletEvent(EventList *ev, Eptr &data)
{
Eptr p;
p = ev->front;
ev->front = p->next;
if (--ev->eventNum<1)
{
ev->rear = ev->front;
}
data = p;
}

/* 删除完成 */



/* 当前客户插入窗口队列 */
void EnQueue(LinkQueue *q, int t1, int t2)
{
Queptr p;
p = new Qnode;
p->arrivetime = t1;
p->duration = t2;
q->length++;
if (q->length == 1) //只有一个元素的队列处理
{
p->next = NULL;
q->front = q->rear = p;
}
else
{
p->next = q->rear->next;
}
q->rear->next = p;
q->rear = p; //重连接队列
}
/* c插入完成 */


/* 当前客户出窗口队列进行处理 */
void DeQueue(LinkQueue *q, Queptr f)
{
Queptr p;
if (q->length>0)
{
f->arrivetime = q->front->arrivetime;
f->duration = q->front->duration;
p = q->front;
q->front = q->front->next;
q->length--;
if (q->length == 0)
q->rear = NULL;
delete (p);
}
}
/* 处理结束 */



/* 找最短队列 */
int Minlength()
{
int min, j, i;
min = q[1].length;
j = 1;
for (i = 2; i <= WINDOW; i++)
if (q[i].length < min)
{
min = q[i].length;
j = i;
}
return j;
}
/* 查询完成 */


/* 初始化银行 */
void Open()
{
int i;
eventlist = new EventList;
pe = new Enode;
pe->occurTime = 0; //初始化发生事件事件
pe->NType = 0;
pe->next = NULL;
eventlist->front = pe; //插入第一个客户到事件表
eventlist->rear = pe;
eventlist->eventNum = 1;


for (i = 1; i < WINDOW + 1; i++) //初始化服务窗口队列为空
{
q[i].front = q[i].rear = NULL;
q[i].length = 0;
}
}
/* 初始化结束 */


/* 客户到达 */
void CustomerArrived()
{
int durtime, intertime, min;
customerNum++; //客流量增加

srand((unsigned)time(NULL));

Sleep(1000);
durtime = 5 + rand() % 31; //产生随机数(当前客户所需的服务时间和下一个用户到达的时间间隔)
intertime = 5 + rand() % 11;


if ((ev->occurTime + intertime) < closetime)
InsertEvent(eventlist, ev->occurTime + intertime, 0); //下一个客户到事件加入事件表

min = Minlength(); //找最短队列
EnQueue(&q[min], ev->occurTime, durtime); //客户加入窗口


cout << "客户于<" << ev->occurTime << ">时刻进入" << min << "号窗口," << "处理了" << durtime << "分钟" << endl;

if (q[min].length == 1)
InsertEvent(eventlist, ev->occurTime + durtime, min); //唯一客户加入离开事件
}
/* 函数结束 */



/* 客户离开 */
void CustomerLeave()
{
int i;
i = ev->NType; //第i号窗的客户离开
Queptr data;
data = new Qnode;
DeQueue(&q[i], data); //删除i号窗口的排头客户

cout << i << "号窗口客户离开" << endl;

totaltime += ev->occurTime - data->arrivetime; //总时间累积

if (q[i].length != 0) //插入离开事件
InsertEvent(eventlist, ev->occurTime + q[i].front->duration, i);
}
/* 函数结束 */



/* 主函数 */
void main()
{
cout << "**************银行模拟系统**************" << endl;
cout << "请输入银行营业时长(分钟):" << endl;
cin >> closetime;

Open(); //初始化银行

while (eventlist->eventNum > 0) //事件非空开始执行
{
DeletEvent(eventlist, ev); //取事件表中的第一个事件节点

if (ev->NType == 0) //处理客户到达事件
CustomerArrived();

else
CustomerLeave(); //处理离开事件
}

cout << "今日客流量:" << customerNum << endl;
cout << "平均处理时间:" << totaltime / customerNum << "分钟" << endl;
system("pause");
}
作者

Wu Rang

发布于

2010-07-10

更新于

2021-12-06

许可协议

评论