从一组定期计时器中挑选下一个计时器值

时间:2013-04-26 22:51:12

标签: c algorithm

我有一个客户列表说(A,B,C,D)有自己的时间段/窗口。我根据下一个窗口到期时间在内部设置了一个计时器......来自(A,B,C,D)的窗​​口大小..

例如:

Client Window Size
A      10
B      15
C      20
D      50

所以计时器到期时间为:10,15,20,30,40,45,50 ......

最好的方法是什么?选择C作为我们的语言来实现。客户端周期存储在静态分配的数组中(我们知道大小)

2 个答案:

答案 0 :(得分:1)

最佳方法是优先级(分钟)堆,优先级基于到期时间。

每次窗口到期时,在O(1)时间内从堆中删除min项,并在过期时间加上O(log(N))时间内的窗口大小重新插入。所需空间为O(N)。

要表示当前时间,至少有两个选项。

1)使用宽值(比如64位)来处理太阳发火的时间

2)使用模运算;这需要仔细比较运算符

对于模数方法,时间值必须至少与最大窗口大小一样大,加上计时器到期延迟的小余量。使用无符号算术。堆中的值应该是插入条目的时间。每个条目的剩余时间是

window - (now - inserted)

请注意,(now - inserted)总是正数,因为它是条目在堆中的长度的度量 - 如果差异“包裹”为零,则无符号结果将是正确的; window也是积极的。如果我们有两个条目xy,我们想看看是否

(x.window - (now - x.inserted)) > (y.window - (now - y.inserted))

我们可以使用

进行无符号算术
(x.window + (now - y.inserted)) > (y.window + (now - x.inserted))

这是我们用来比较堆条目的比较运算符。

答案 1 :(得分:0)

取决于您添加客户端的频率以及窗口大小的大小,我会考虑使用此方法:

  1. 将m定义为最大窗口大小:m = max(Window Size)

  2. 然后你可以分配布尔数组:bool Alarms[m]

  3. 对于每个客户端集:Alamrs[k*windowsize]=true其中k的范围为<1, m/windowsize>

    • 在您的示例中,警报将如下所示: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 ... 警报[10] = TRUE; 警报[15] = TRUE; 警报[20] = TRUE; 警报[30] = TRUE; 等
  4. 警报的每个刻度线检查Alarms[tick % m]的值。当你读到真正的警报应该响起。阅读状态为O(1)。

    当Window Sizes类似且你不经常添加窗口大小更高的客户端时,这种方法很好。

    • 添加窗口大小&gt;的客户端时你必须重新分配整个阵列,这可能很昂贵。

    • 当客户端窗口之间有大的空格时 - 例如A = 1且B = 30000,您需要29998个空单元格。