您的位置:首页 > 编程语言 > C语言/C++

数据机构与算法分析:C语言描述 第五章——Priority Queues(Heaps)中的5.4.2 Event Simiulation

2015-09-24 16:46 501 查看
  在《数据结构与算法分析——C语言描述》英文第二版中的第五章——Priority Queues(Heaps)中的5.4.2 Event Simiulation。我对于这个例子的理解挺困难。

在书中描述的是一个银行中顾客排队等待出纳(teller)服务的情景。对于其中的事件模拟是先利用probality distribution function(概率函数?)来生成一个顾客的输入队列,队列中放入顾客的到达时间和其需要的服务时间(这两个时间成对出现,叫ordered pairs)。出纳的个数为k,事件的模拟是计算和存储相应的时间段信息,所以不需要真是的时间点,可以假设一个单位时间,并以此计算和存储事件发生的时刻和事件发生时间长度。单位时间叫做tick(滴答)。

  好了,先决假设都有了,可以开始正式模拟事件了。对于银行来说,遇到的事件无非是两个:一个顾客的到来和正在接受服务的顾客的离开。这里注意一下,当一个顾客到来时并不是可以立即接受服务,而是要进入等待的队列中,这个与现实情景相同。这时对于模拟程序来说,可以有两种思路来检查事件发生的思路(从这开始就比较绕)。

  第一种思路

  从银行开张开始将tick设为0,并设置一个自动运行的时钟,时钟每次走动一个tick的时间。时钟没走动一次,就对银行的状态进行检测,检测出纳柜台是否空出座位和检测等待区域是否有顾客排队,并认为如果全部出纳都处于空闲之中并且没有顾客在等待,那么这个模拟事件就圆满结束,大家可以高兴的喝茶聊天。

  但是这个思路有一个缺陷,就是当服务的顾客离开一位并且此时银行并没有下班时,也暂时没有排队等待的顾客,此时银行仍然在运作之中。那么模拟系统就会继续根据自动运行的时钟的走动,每隔一个tick就检查一边服务窗口和排队区域。看起来这样也没有什么问题,只是此时模拟系统仅仅在不停的循环检测并等待事件发生。但事实上(书中的一个弯),模拟系统毕竟不是真是情景,时间的流失也不没必要一直要以时钟的步伐一步一步地向前耿直的前进。就像是网络上的视频有两种模式:直播和录像,而此时的情况更像是录像。直播中我们无法向前推进进度,只能等待事件依次发生,但在看录像时,因为事件早已发生并记录,所以我们可以跳过一场比赛的现场广告和中场休息,直接去看空闲后的内容。这里的银行情景模拟也是如此,当我们设定一个时钟,并按照时钟的拍数一步一步的循环检测事件时,在两个事件发生的间隙,我们就必须在那里做循环检测,所以在模拟系统的运行时间上来说就会比较长(相对于跳过这些循环等待)。这时候书中说如果将时钟的每一步设定为tick的千分之一并将输入的顾客事件的设定时间全部乘以1000,那么运行结果将会是之前的1000倍。

  我的疑问也就是上一段的最后一句话。如果将顾客的事件时间输入队列的值均乘以1000,例如输入队列中原有的值是:1,4,10,……(单位是tick),即在tick1时来了一个顾客,他需要服务的时间为4个tick。那么此时输入队列就会变为:1000,4000,10000……原先相邻两位顾客到来的时间间隔为:10-1=9个tick;现在相邻两位顾客的到达时间间隔就变为了:10000-1000=9000个tick,这个两个时间间隔的差距十分明显,“空循环检测”也会增长很多。但是,有必要加上假设 “将时钟每一步的事件单位变为1 tick的千分之一” 吗?1个tick在程序中运行的时间与1000个millitick(千分之tick)的运行时间相同,区别仅仅是在程序必须要运行这1tick的时间时,1 tick的时钟单位只会检测一次银行状况,而千分之tick的时钟单位系统会循环检测1000次银行状况。然而对于运行时间而言并没有什么区别,该空循环的事件仍然在空循环。这里我觉的那个“we changed the clock units to milliticksd” 这一句话是多余的。

  第二种思路

  取消那个接近自然状态的运行时钟,而像事件查找器一样,查找下一个最近要发生的事件的时间点,然后直接跳到那个时间点去作业。没有了空循环,而那些事件时间点的计算又是哪种方法都需要的,所以大大减少了模拟系统运行的效率,相当于模拟系统从处理直播中的事件变为处理录像中的事件,可以跳过中间的等待,减少了运行时间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: