基于驱逐的TTL(生存时间)优先级队列

时间:2017-01-27 10:33:14

标签: java algorithm priority-queue

我需要一个满足以下属性的数据结构: -

  1. 在O(1)
  2. 中获取最大值
  3. 插入O(log n)
  4. 删除O(log n)中的最大值(O(log n)中删除ANY时的加值点)
  5. 只有在超过特定TTL(生存时间)时才会调用删除。
  6. 操作4只需要最终保持一致,但有限的时间复杂度将是非常好的。

    1,2和3是使用堆数据结构的标准优先级队列。但是,如果没有自己实施驱逐线程,我认为没有任何方法可以实现4.我有两个问题:

    • 实施4的最佳方法是什么?
    • 是否存在Java或任何其他基于JVM的lang中的现有实现,我可以直接使用它而无需自己编写驱逐策略?

1 个答案:

答案 0 :(得分:1)

是的,标准二进制堆将提供您的要求,但在O(log n)中删除any除外。

您可以实现skip list优先级队列,其中包含O(1)get max,O(log n)插入,O(1)delete max,O(log n)delete any。

Pairing heap有O(1)得到最大值,O(1)插入,摊销O(log n)删除最大值。您可以使用其他数据结构实现O(log n)(再次,摊销)删除any。

根据我的经验,配对堆比跳过列表更容易实现。

对于驱逐通知,我建议计算驱逐时间,并将其用作优先级队列中的密钥。然后,我使用计时器通知我何时调用删除。

  1. 在程序启动时,初始化nextRemovalTime值以在下次删除项目时保留。将初始值设置为远期。设置一个会在那时通知您的计时器。
  2. 要将项目添加到队列,请通过将TTL添加到当前时间来计算到期时间。然后将项目插入队列。
  3. nextRemovalTime与队列头部项目的删除时间进行比较。
  4. 如果队列头部的项目早于nextRemovalTime,则取消现有计时器,将nextRemovalTime设置为应删除第一个节点的时间,然后重新初始化计时器
  5. 这里的想法是,当计时器滴答时,会创建一个后台线程,并将删除顶部项目。以及其他时间已到期的物品。然后计算新的删除时间并重新初始化计时器。

    该方法的缺点是优先级队列数据结构必须能够处理并发访问。通常,这是一个锁,除非您有一个无锁的并发优先级队列。它确实不是问题,除非队列被频繁命中。

    另一种方法是,如果您并不十分担心队列增长过大,那么无论何时添加新项目或删除现有项目,都要检查过期项目。也就是说,插入变为:

    while (queue.peek().expirationTime < currentTime)
    {
        queue.removeMax();
    }
    queue.insert(newItem);