查看源代码 queue (stdlib v6.2)
FIFO 队列的抽象数据类型。
此模块以高效的方式提供(双端)FIFO 队列。
如果参数类型错误,例如,队列参数不是队列,索引不是整数,列表参数不是列表,所有函数都会因 badarg
的原因而失败。不正确的列表会导致内部崩溃。队列的索引超出范围也会导致因 badarg
的原因而失败。
某些函数(在有说明的情况下)会因空队列而导致 empty
的原因而失败。
此模块使用的表示队列的数据将被其他模块视为不透明的。从抽象的角度来看,该表示是现有 Erlang 项的复合类型。请参阅有关数据类型的说明。任何假设了解格式的代码都非常不安全。
所有操作都具有分摊的 O(1) 运行时间,除了 all/2
、any/2
、delete/2
、delete_r/2
、delete_with/2
、delete_with_r/2
、filter/2
、filtermap/2
、fold/3
、join/2
、len/1
、member/2
、split/2
,它们具有 O(n) 的时间复杂度。为了最小化队列的大小,并最小化队列操作产生的垃圾数量,队列不包含显式的长度信息,这就是为什么 len/1
的时间复杂度为 O(n) 的原因。如果对于此特定操作需要更好的性能,则调用者很容易跟踪长度。
队列是双端的。队列的心理图景是一队人(项)在等待轮到他们。队列前端是等待时间最长的项所在的末端。队列尾部是项开始等待时进入的末端。如果改为使用列表的心理图景,则前端称为头部,尾部称为尾部。
从前端进入并在后端退出是队列上的反向操作。
此模块有三组接口函数:“原始 API”、“扩展 API” 和 “Okasaki API”。
“原始 API”和“扩展 API”都使用等待项队列的心理图景。两者都有后缀为“_r”的反向操作。
“原始 API”项删除函数返回包含已删除项和结果队列的复合项。“扩展 API”包含构建更少垃圾的替代函数,以及仅用于检查队列末端的函数。此外,“Okasaki API”函数构建的垃圾也更少。
“Okasaki API”的灵感来自 Chris Okasaki 的《纯函数式数据结构》。它将队列视为列表。许多人认为此 API 很奇怪且可以避免。例如,许多反向操作的名称在词法上是相反的,有些名称更易读但可能不太容易理解的别名。
摘要
原始 API
如果 Pred(Item)
对 Q
中的所有项 Item
返回 true
,则返回 true
,否则返回 false
。
如果 Pred(Item)
对 Q
中至少一个项 Item
返回 true
,则返回 true
,否则返回 false
。
返回 Q1
的副本,其中删除了第一个匹配 Item
的项(如果有)。
返回 Q1
的副本,其中删除了最后一个匹配 Item
的项(如果有)。
返回 Q1
的副本,其中删除了第一个 Pred
返回 true
的项(如果有)。
返回 Q1
的副本,其中删除了最后一个 Pred
返回 true
的项(如果有)。
返回一个队列 Q2
,它是对 Q1
中的所有项调用 Fun(Item)
的结果。
返回一个队列 Q2
,它是对 Q1
中的所有项调用 Fun(Item)
的结果。
在 Queue
的连续项 Item
上调用 Fun(Item, AccIn)
,从 AccIn == Acc0
开始。队列按队列顺序遍历,即从前到后。Fun/2
必须返回一个新的累加器,该累加器将传递给下一次调用。该函数返回累加器的最终值。如果队列为空,则返回 Acc0
。
返回一个包含 L
中各项的队列,顺序相同;列表的头部项成为队列的前端项。
将 Item
插入队列 Q1
的尾部。返回结果队列 Q2
。
将 Item
插入队列 Q1
的前端。返回结果队列 Q2
。
测试 Q
是否为空,如果为空则返回 true
,否则返回 false
。
测试 Term
是否为队列,如果是则返回 true
,否则返回 false
。请注意,即使不是由此模块构造的,对于与队列的表示形式一致的项,此测试也会返回 true
。另请参阅有关数据类型的说明。
返回一个队列 Q3
,它是将 Q1
和 Q2
连接的结果,其中 Q1
在 Q2
的前面。
计算并返回队列 Q
的长度。
如果 Item
与 Q
中的某个元素匹配,则返回 true
,否则返回 false
。
返回一个空队列。
删除队列 Q1
前端的项。返回元组 {{value, Item}, Q2}
,其中 Item
是删除的项,Q2
是结果队列。如果 Q1
为空,则返回元组 {empty, Q1}
。
删除队列 Q1
后端的项。返回元组 {{value, Item}, Q2}
,其中 Item
是删除的项,Q2
是新队列。如果 Q1
为空,则返回元组 {empty, Q1}
。
返回一个队列 Q2
,其中包含 Q1
的项,顺序相反。
将 Q1
分成两部分。前面的 N
项放入 Q2
,其余放入 Q3
。
返回队列中各项的列表,顺序相同;队列的前端项成为列表的头部。
扩展 API
返回一个队列 Q2
,它是从 Q1
中删除前端项的结果。
返回一个队列 Q2
,它是从 Q1
中删除后端项的结果。
返回队列 Q
前端的 Item
。
返回队列 Q
后端的 Item
。
返回元组 {value, Item}
,其中 Item
是 Q
的前端项,如果 Q
为空,则返回 empty
。
返回元组 {value, Item}
,其中 Item
是 Q
的后端项,如果 Q
为空,则返回 empty
。
Okasaki API
将 Item
插入队列 Q1
的头部。返回新队列 Q2
。
返回队列 Q
的尾部项。
从队列 Q
的头部返回 Item
。
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
返回队列 Q
的尾部项。
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
将 Item
作为队列 Q1
的尾部项插入。返回新队列 Q2
。
返回一个队列 Q2
,它是从 Q1
中删除头部项的结果。
类型
原始 API
如果 Pred(Item)
对 Q
中的所有项 Item
返回 true
,则返回 true
,否则返回 false
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
2> queue:all(fun (E) -> E > 3 end, Queue).
false
3> queue:all(fun (E) -> E > 0 end, Queue).
true
如果 Pred(Item)
对 Q
中至少一个项 Item
返回 true
,则返回 true
,否则返回 false
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
2> queue:any(fun (E) -> E > 10 end, Queue).
false
3> queue:any(fun (E) -> E > 3 end, Queue).
true
返回 Q1
的副本,其中删除了第一个匹配 Item
的项(如果有)。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
2> Queue1 = queue:delete(3, Queue).
3> queue:member(3, Queue1).
false
返回 Q1
的副本,其中删除了最后一个匹配 Item
的项(如果有)。
示例
1> Queue = queue:from_list([1,2,3,4,3,5]).
2> Queue1 = queue:delete_r(3, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
-spec delete_with(Pred, Q1) -> Q2 when Pred :: fun((Item) -> boolean()), Q1 :: queue(Item), Q2 :: queue(Item), Item :: term().
返回 Q1
的副本,其中删除了第一个 Pred
返回 true
的项(如果有)。
示例
1> Queue = queue:from_list([100,1,2,3,4,5]).
2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
-spec delete_with_r(Pred, Q1) -> Q2 when Pred :: fun((Item) -> boolean()), Q1 :: queue(Item), Q2 :: queue(Item), Item :: term().
返回 Q1
的副本,其中删除了最后一个 Pred
返回 true
的项(如果有)。
示例
1> Queue = queue:from_list([1,2,3,4,5,100]).
2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).
3> queue:to_list(Queue1).
[1,2,3,4,5]
-spec filter(Fun, Q1 :: queue(Item)) -> Q2 :: queue(Item) when Fun :: fun((Item) -> boolean() | [Item]).
返回一个队列 Q2
,它是对 Q1
中的所有项调用 Fun(Item)
的结果。
如果 Fun(Item)
返回 true
,则 Item
被复制到结果队列。如果它返回 false
,则不复制 Item
。如果它返回一个列表,则列表元素将插入结果队列,而不是 Item
。
示例 1
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).
{[5],[3,4]}
3> queue:to_list(Queue1).
[3,4,5]
因此,Fun(Item)
返回 [Item]
在语义上等同于返回 true
,正如返回 []
在语义上等同于返回 false
一样。但返回一个列表比返回一个原子会产生更多的垃圾。
示例 2
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).
{[6,5,5,4,4,3],[1,2,2,3]}
3> queue:to_list(Queue1).
[1,2,2,3,3,4,4,5,5,6]
-spec filtermap(Fun, Q1) -> Q2 when Fun :: fun((Item) -> boolean() | {true, Value}), Q1 :: queue(Item), Q2 :: queue(Item | Value), Item :: term(), Value :: term().
返回一个队列 Q2
,它是对 Q1
中的所有项调用 Fun(Item)
的结果。
如果 Fun(Item)
返回 true
,则 Item
将被复制到结果队列中。如果它返回 false
,则 Item
不会被复制。如果它返回 {true, NewItem}
,则结果队列中此位置的队列元素将被替换为 NewItem
。
示例 1
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).
{[5],[3,4]}
3> queue:to_list(Queue1).
[3,4,5]
4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).
{"ihg","ef"}
5> queue:to_list(Queue1).
"efghi
-spec fold(Fun, Acc0, Q :: queue(Item)) -> Acc1 when Fun :: fun((Item, AccIn) -> AccOut), Acc0 :: term(), Acc1 :: term(), AccIn :: term(), AccOut :: term().
在 Queue
的连续项 Item
上调用 Fun(Item, AccIn)
,从 AccIn == Acc0
开始。队列按队列顺序遍历,即从前到后。Fun/2
必须返回一个新的累加器,该累加器将传递给下一次调用。该函数返回累加器的最终值。如果队列为空,则返回 Acc0
。
示例
1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).
15
2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).
120
-spec from_list(L :: [Item]) -> queue(Item).
返回一个包含 L
中各项的队列,顺序相同;列表的头部项成为队列的前端项。
将 Item
插入队列 Q1
的尾部。返回结果队列 Q2
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:in(100, Queue).
{[100,5,4,3],[1,2]}
3> queue:to_list(Queue1).
[1,2,3,4,5,100]
将 Item
插入队列 Q1
的前端。返回结果队列 Q2
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue1 = queue:in_r(100, Queue).
{[5,4,3],[100,1,2]}
3> queue:to_list(Queue1).
[100,1,2,3,4,5]
测试 Q
是否为空,如果为空则返回 true
,否则返回 false
。
测试 Term
是否为队列,如果是则返回 true
,否则返回 false
。请注意,即使不是由此模块构造的,对于与队列的表示形式一致的项,此测试也会返回 true
。另请参阅有关数据类型的说明。
返回一个队列 Q3
,它是将 Q1
和 Q2
连接的结果,其中 Q1
在 Q2
的前面。
示例
1> Queue1 = queue:from_list([1,3]).
{[3],[1]}
2> Queue2 = queue:from_list([2,4]).
{[4],[2]}
3> queue:to_list(queue:join(Queue1, Queue2)).
[1,3,2,4]
-spec len(Q :: queue()) -> non_neg_integer().
计算并返回队列 Q
的长度。
如果 Item
与 Q
中的某个元素匹配,则返回 true
,否则返回 false
。
返回一个空队列。
删除队列 Q1
前端的项。返回元组 {{value, Item}, Q2}
,其中 Item
是删除的项,Q2
是结果队列。如果 Q1
为空,则返回元组 {empty, Q1}
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> {{value, 1=Item}, Queue1} = queue:out(Queue).
{{value,1},{[5,4,3],[2]}}
3> queue:to_list(Queue1).
[2,3,4,5]
删除队列 Q1
后端的项。返回元组 {{value, Item}, Q2}
,其中 Item
是删除的项,Q2
是新队列。如果 Q1
为空,则返回元组 {empty, Q1}
。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).
{{value,5},{[4,3],[1,2]}}
3> queue:to_list(Queue1).
[1,2,3,4]
返回一个队列 Q2
,其中包含 Q1
的项,顺序相反。
-spec split(N :: non_neg_integer(), Q1 :: queue(Item)) -> {Q2 :: queue(Item), Q3 :: queue(Item)}.
将 Q1
分成两部分。前面的 N
项放入 Q2
,其余放入 Q3
。
-spec to_list(Q :: queue(Item)) -> [Item].
返回队列中各项的列表,顺序相同;队列的前端项成为列表的头部。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> List == queue:to_list(Queue).
true
扩展 API
返回一个队列 Q2
,它是从 Q1
中删除前端项的结果。
如果 Q1
为空,则会因 empty
原因而失败。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue = queue:drop(Queue).
{[5,4,3],[2]}
3> queue:to_list(Queue1).
[2,3,4,5]
返回一个队列 Q2
,它是从 Q1
中删除后端项的结果。
如果 Q1
为空,则会因 empty
原因而失败。
示例
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> Queue = queue:drop_r(Queue).
{[4,3],[1,2]}
3> queue:to_list(Queue1).
[1,2,3,4]
-spec get(Q :: queue(Item)) -> Item.
返回队列 Q
前端的 Item
。
如果 Q
为空,则会因 empty
原因而失败。
示例 1
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> 1 == queue:get(Queue).
true
-spec get_r(Q :: queue(Item)) -> Item.
返回队列 Q
后端的 Item
。
如果 Q
为空,则会因 empty
原因而失败。
示例 1
1> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
2> 5 == queue:get_r(Queue).
true
-spec peek(Q :: queue(Item)) -> empty | {value, Item}.
返回元组 {value, Item}
,其中 Item
是 Q
的前端项,如果 Q
为空,则返回 empty
。
示例 1
1> queue:peek(queue:new()).
empty
2> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
3> queue:peek(Queue).
{value, 1}
-spec peek_r(Q :: queue(Item)) -> empty | {value, Item}.
返回元组 {value, Item}
,其中 Item
是 Q
的后端项,如果 Q
为空,则返回 empty
。
示例 1
1> queue:peek_r(queue:new()).
empty
2> Queue = queue:from_list([1,2,3,4,5]).
{[5,4,3],[1,2]}
3> queue:peek_r(Queue).
{value, 5}
Okasaki API
将 Item
插入队列 Q1
的头部。返回新队列 Q2
。
示例
1> Queue = queue:cons(0, queue:from_list([1,2,3])).
{[3,2],[0,1]}
2> queue:to_list(Queue).
[0,1,2,3]
-spec daeh(Q :: queue(Item)) -> Item.
返回队列 Q
的尾部项。
如果 Q
为空,则会因 empty
原因而失败。
示例 1
1> queue:daeh(queue:from_list([1,2,3])).
3
-spec head(Q :: queue(Item)) -> Item.
从队列 Q
的头部返回 Item
。
如果 Q
为空,则会因 empty
原因而失败。
示例 1
1> queue:head(queue:from_list([1,2,3])).
1
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
如果 Q1
为空,则会因 empty
原因而失败。
示例
1> Queue = queue:init(queue:from_list([1,2,3])).
{[2],[1]}
2> queue:to_list(Queue).
[1,2]
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
如果 Q1
为空,则会因 empty
原因而失败。
名称 lait/1
是拼写错误 - 请勿再使用它。
-spec last(Q :: queue(Item)) -> Item.
返回队列 Q
的尾部项。
如果 Q
为空,则会因 empty
原因而失败。
示例
1> queue:last(queue:from_list([1,2,3])).
3
返回一个队列 Q2
,它是从 Q1
中删除尾部项的结果。
如果 Q1
为空,则会因 empty
原因而失败。
示例
1> Queue = queue:liat(queue:from_list([1,2,3])).
{[2],[1]}
2> queue:to_list(Queue).
[1,2]
将 Item
作为队列 Q1
的尾部项插入。返回新队列 Q2
。
示例
1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
{[4,3,2],[1]}
2> queue:to_list(Queue).
[1,2,3,4]
返回一个队列 Q2
,它是从 Q1
中删除头部项的结果。
如果 Q1
为空,则会因 empty
原因而失败。