特殊的队列

时间:2010-03-21 18:19:17

标签: java collections queue

我正在寻找类似Queue的东西,它允许我将元素放在队列的末尾并在开头弹出它们,就像常规的Queue一样。

不同之处在于我还需要不时压缩队列。这是,假设我的队列中有以下项目(每个字符,包括点,是队列中的项目):

e d . c . b . a
(this Queue has 8 items)

然后,我需要例如删除最后一个点,所以得到:

e d . c . b a

Java Collection类中有类似的东西吗?我需要将它用于我正在做的程序,除了Java的类之外我不能使用任何东西。我不被允许为自己设计一个。目前我只是使用LinkedList,但我想这可能更像是一个Queue而不是LinkedList。

由于

修改

基本上这是项目的内容: 交通信号灯可以是绿色(和相关的符号是' - ')或红色('|')。交通灯在右边: alt text http://img684.imageshack.us/img684/9602/0xfhiliidyxdy43q5mageu0.png 在开始时,你没有任何汽车,交通信号灯是绿色的,所以我们的清单表示为:

.......  -

现在,在下一次迭代中,我有一个随机变量,可以告诉我哪里有车来了。如果有车来,那么我们可以看到它从左边出现。在每次迭代中,所有汽车向右移动一步。如果他们右边有任何车,那么他们就无法动弹:

a......  -   (iteration 1)
.a.....  -   (iteration 2)
..a....  -   (iteration 3)

现在,发生的事情是交通信号灯有时会变红(' - ')。在这种情况下,如果你有几辆车,那么即使他们在移动时有一些距离,当他们必须停在交通灯时他们会接近:

...b.a.  -   (iteration n)
....b.a  -   (iteration n+1)
.....ba  -   (iteration n+2) here they got close to each other

现在,这就是为什么它像队列一样工作的原因,但有时我必须取下那些点,当汽车靠近红色交通灯时。 还要记住,这里街道的大小是7个字符,但它有时会增长,所以我们不能假设这是一个固定长度列表。

4 个答案:

答案 0 :(得分:4)

队列基本上是具有已定义行为的项目列表,在本例中为FIFO(先进先出)。您可以在最后添加项目,并从头开始删除它们。

现在可以以您选择的任何方式实施队列;使用链接列表或使用数组。我认为你走的是正确的道路。链表肯定会让它变得更容易。

您将有O(1)用于添加和删除您的队列(如果您保持对前面和后面的引用),但压缩(删除点)的最坏情况将是O (N)。

如果您使用辅助数据结构,我相信可能有办法将compact操作减少到O(1)(如果您一次只删除一个点)。你需要的是另一个队列(使用另一个链表实现),它保持对第一个链表中点的引用。

因此,当你插入(a,。,b,c,。,d)时,你有一个如下所示的列表:

[pointer to rear] -> [d] -> [.] -> [c] -> [b] -> [.] -> [a] <- [pointer to front]

并且您还有一个辅助队列(实现为链接列表),用于维护对点的引用:

[pointer to rear] -> [reference to second dot] -> [reference to first dot] <- [pointer to front]

然后,当您需要执行compact操作时,您所要做的就是从第二个队列中删除第一个元素并保留引用。因此,您现在可以引用位于第一个链接列表中间的点。您现在可以轻松地从第一个列表中删除该点。

您在评论中提到需要跟踪订单。根据定义,队列是一个有序的结构(从某种意义上说,事物按照它们的插入顺序保留)。因此,当您在第一个队列中插入一个点时,您需要做的就是将点的引用插入第二个队列。这样,维持秩序。因此,当您从第二个队列中取消对点的引用时,您可以引用第一个队列中的实际和相应的点。

这里对速度的权衡是你需要更多的内存,因为你要维护第二个引用列表。最坏情况内存要求是您现在使用的2倍。但是,获得O(1)vs O(n)是一个不错的权衡。

答案 1 :(得分:3)

我想说LinkedList是最好的方法......因为LinkedList允许你从前/后推/弹,并允许你删除列表中间的项目。

显然,查找时间很糟糕,但是如果你更频繁地从列表的前面/后面添加/删除然后查找,那么我会说坚持使用LinkedList。

答案 2 :(得分:3)

家庭作业/学校项目总是很棘手,为可能会让某人的大脑融化的要求添加微妙的东西。您是否有要求将空格包含在队列中?

就个人而言,除非明确要求,否则我不会这样做:将汽车表示为Car,Space对,(您可以将该对定义为结构,假设您可以使用结构)似乎更简单,其中空间为表示车辆中下一辆车的空间的数值。然后,要压缩,您只需要查看列表项:当您找到具有Space > 0的项目时,执行Space--; return;,并且所有其他汽车将已经“高级”,因为它们保留了空间与他们面前的人。为了输出,请务必在之后(如果红绿灯位于右侧并且车辆来自左侧)或之前(左侧的红绿灯和右侧的车辆)之后为每辆车抛出Space点。本身,你走了。另请注意,第一辆车的Space表示与红绿灯本身的距离,因为它前面没有车。

如果你向结构添加指向下一辆车的指针(以及最后一辆车的空指针),你已经有了一个链表:保留一个指向第一辆车的“全局”变量(或者为空队列)。由于Java不直接支持指针,所以将结构转换为类并使用“对象引用”(除了C'ish指针算术之外的所有目的都与指针相同),然后你去:只有一个类,内置从头开始。您需要从Java库中触及的唯一事情是标准IO,也许还有一些字符串操作,这是必须从输入和产生输出中获得的固有需求(一些大学有自己的课程特定的IO图书馆,但这不会产生很大的不同)。要遍历队列,你可以做这样的事情(假设这个类被命名为“Node”,这是非常通用的,并且显示了字段的明显名称):

for(Node pos = First; pos != null; pos = pos.Next) {
    /* Do your stuff here, knowing that "pos" points to the "current" item on each iteration. */
}

要添加新节点,您可能需要遍历队列以确定新车“生成”时距离最后一个的距离;当你这样做时,保留最后一个节点的引用,并使其“下一个”引用指向新节点:

Node last = First;
int distance = 0;
for(Node pos = First; pos != null; pos=pos.Next) {
    distance += pos.Space;
    last = pos;
}
last.Next = new Node(the_letter_for_this_car, MaxDistance-distance, null);

当然,将构造函数调整为您拥有的任何内容。

考虑到这是一个大学项目,让我们来看看一些细节:紧凑的处理时间变为O(n),它的内存使用量为O(0)(该过程本身不需要任何“本地” “变量,除了可能是遍历集合的指针,它独立于队列的长度。”此外,队列本身的内存使用量保证小于或等于将空格表示为项目的内存使用量(只有在最糟糕的情况下,当有足够的汽车停在红灯处时,它才会相等)。因此,除非要求包含与此方法不相符的内容,否则我希望这是您老师想要的:它是合理的,有效的,并且符合您的要求。

希望这有帮助。

答案 3 :(得分:1)

可能是第二个保留点元素的LinkedList?