数据结构队列之离散事件模拟

一、什么是离散事件

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.有序队列:队列按照时间顺序写入(先来后到)。

核心思想:将自己想象成一个会穿越的摄影师(按时间顺序记录发生的事情),有序事件链表则是一个影像清单,指示着你去拍哪些东西,而不考虑中间发生了什么,你不会在那里拍摄事件发生前后的事情,只是当事情发生时,直接去拍画面,就像是直接穿越到那一瞬间一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值