一、什么是离散事件
1.离散事件:
是指系统中发生的,在时间点上瞬间完成的事,而系统的状态不是连续变化的,而是在一系列的时间点上瞬间完成,在两个事件之间,系统的状态保持不变。
2.核心思想:
模拟时钟不是滴答滴答地均匀前进,而是由事件驱动,从一个事件直接跳到另一个事件。
3.与时间步长法的区别:
1.时间步长法:将时间分成很多小段,检查每一小段时间发生的事件,这种发放虽然简单,但是效率低。
2.离散事件模拟法:
只关注事件发生的时间点,时钟直接跳到下一个时间点。
二、用离散事件模拟客户到银行办理业务的平均等待时间
问题阐述:
假设某银行有4个窗口,客户随机到达银行,办理业务的时间也是随机的,模拟出银行一天营业中顾客的平均等待时长。
三、核心数据结构
1.有序链表(Event List):用来表示所有“未来将要发生的事件”,并以事件发生的时间顺序排序。
2. 队列(Queue):对应4个窗口,先入队列的客户先办理业务,模拟客户排队。
四、关键数据结构定义
1.数据类型定义:事件的两个关键点:发生时间和事件类型

2.客户队列元素:每一个元素代表一个客户(包含两个信息)

3.队列结点(链式队列):

4.队头队尾指针(方便直接出队入队)

5.事件类型

五、算法流程
程序围绕着一个主循环进行,循环的每一步处理当前最近的一个事件
步骤1.
a.初始化一个空的事件链表
![]()
b.设置4 个队列代表4个空闲窗口。


c.初始化第一个客户到达事件:en

d.将改事件插入到事件表中:模拟事件的起点
OrderInsert函数使ev事件链表中的事件按时间顺序排列(例如,A在0时刻进银行,办理业务5分钟,B在3时刻进银行,则B进银行事件在A出银行事件的前面)

步骤2.
进入主循环,只要链表不为空,就执行下列语句

步骤3.
取当前事件,即事件表中最靠前的那个事件。从事件链表中取出最早发生的事件,由于链表中的事件是按照时间顺序有序排列的(p= ev;ev= ev->next;)
a.判断当前事件是到达事件还是离开事件(ntype==0表示到达,1,2,3,4分别代表从哪个窗口离开)
若是到达事件:
*客户数CustomerNum+1
*随机生成该客户的办理业务所需时间durtime以及下一个客户到达时间间隔intertime

*判断下一个客户到达是银行是否关门(即该客户到达事件发生时刻+下一个客户到达的时间间隔)
若没关门:将下一个客户en的到达事件写入到事件链表ev中

*处理当前客户customer
找到最短的队列,该客户入队q[min]


*判断该队列长度q[i].length是否为1
如果为1,说明窗口空闲,不用等其他人办理完业务,直接办理,即紧接着执行下一个事件en,并将其写在事件表ev上

若是离开事件(ev->ntype==1,2,3,4)代表从1,2,3,4窗口离开
*该客户customer出队q[ntype],并将其信息传递到新的变量customer 中
*计算该客户的等待时间waitTime = occurtime(事件发生时刻,客户离开时间)-customer.arrivaltime(客户到达时间)-customer.duration(该客户办理业务所需时间);
*判断队列中是否还有人在等待(判断队列是否为空,即length是否==0)
1.取出队首客户信息
2,将该客户信息存入到en中(客户到达时间arrivaltime,需要服务的时间durtion,服务窗口ntype)
3.将事件en插入到事件表ev中

客户出队函数

主函数

六、总结
1.时间跳跃:从当前时间点直接跳到下一个时间点,忽略过程。
2.事件驱动:该事件全靠到达,离开事件驱动,从事件链表中依次发生。
3.有序链表:事件按照时间顺序写入链表中,保证每次取得的事件都是最早发生的。
4.有序队列:队列按照时间顺序写入(先来后到)。
核心思想:将自己想象成一个会穿越的摄影师(按时间顺序记录发生的事情),有序事件链表则是一个影像清单,指示着你去拍哪些东西,而不考虑中间发生了什么,你不会在那里拍摄事件发生前后的事情,只是当事情发生时,直接去拍画面,就像是直接穿越到那一瞬间一样。
2924

被折叠的 条评论
为什么被折叠?



