持久队列数据结构

时间:2014-01-14 08:18:15

标签: java data-structures

我需要创建一个类Persistent队列,其中函数enqueue将元素排入当前队列并返回新队列。原始队列如何保持不变。类似地,dequeue函数删除前面元素,返回新队列,但原始队列保持不变。这当然可以在O(队列长度)中完成,但我可以更快地完成。??

3 个答案:

答案 0 :(得分:2)

您可以使用链接列表作为队列(不是LinkedList,而是您自己的实现)。

要添加新元素,您只需创建队列类的新实例,将其start元素设置为复制队列的start元素,然后创建新的end元素。

删除元素类似,但将新队列的结束元素设置为复制队列的倒数第二个元素。

队列类可能如下所示:

static class Node {
    final Node next;
    final Object o;
    Node(Node next, Object o) {...}
}

final Node start, end;

private Queue(Node start, Node end) {...}

public Queue(Object o) {
    start = end = new Node(null, o);
}

public Queue add(Object o) {
    return new Queue(start, new Node(end, o));
}

public Queue remove() {
    return new Queue(start, end.next);
}

此队列的addremove方法的复杂性为O(1)。

请注意,您只能以相反的顺序迭代此队列(即首先是最新的元素)。也许你可以想出一些可以反过来甚至两个方向迭代的东西。

答案 1 :(得分:2)

我建议看看scala的实现。该课程顶部的注释描述了所选择的方法(复杂性:O(1))。

  

Queue实现为一对List s,其中一个包含''in''元素,另一个包含'out'元素。     
元素将添加到“输入”列表中,并从“输出”列表中删除。当''out''列表运行干涸时,    通过将''out''列表替换为'in.reverse''和''in''''''Nil''来转移队列。    

将项目添加到队列中的成本始终为O(1)。除案例外,删除项目的费用为O(1)    需要透视的地方,在这种情况下,会产生O(n)的成本,其中n是队列中元素的数量。当这个情况发生时,    保证以n费用删除O(1)次删除操作。删除项目的平均值为O(1)

http://xuwei-k.github.io/scala-library-sxr/scala-library-2.10.0/scala/collection/immutable/Queue.scala.html

答案 2 :(得分:0)

我所做的是使用Java Chronicle(免责声明:我写的)。这是一个无限制的关闭堆持久队列,存储在磁盘或tmpfs(共享内存)上。

在这种方法中,您的消费者会记录队列中的位置,但实际上没有删除任何条目(除了每日或每周维护周期)

这样就可以避免在添加队列时更改队列,而且不需要复制队列。

因此,维护对每个消费者认为的位置的多个引用,对于每个消费者来说,队列的尾部是O(1)。

由于Chronicle使用紧凑的二进制形式,因此您可以存储的数量限制受磁盘空间的限制。例如在必须轮换队列日志之前,2 TB驱动器甚至可以在8 GB的机器上存储这么多数据。