1. 程式人生 > 其它 >erlang 佇列(queue)模組

erlang 佇列(queue)模組

技術標籤:erlang

queue模組部分api說明


文章目錄


queue:new -> {[], []}

新建一個佇列,返回兩個為空的列表組成的元組

queue:is_queue -> boolean | badarg

是否是佇列,通過判斷元組是否由兩個列表組成

queue:is_empty -> boolean | badarg

是否為空佇列,通過判斷兩個列表是否為空

queue:len -> integer | badarg

佇列長度,通過獲取兩個列表長度相加實現

queue:to_list({In,Out}) -> list | badarg

佇列轉為列表,由Out列表拼接反轉後的In列表實現

queue:from_list(L) -> queue | badarg

列表轉為佇列,呼叫了f2r

f2r([]) ->
    {[],[]};
f2r([_]=F) ->
    {F,[]};
f2r([X,Y]
) -> {[Y],[X]}; f2r(List) -> {FF,RR} = lists:split(length(List) div 2 + 1, List), {lists:reverse(RR, []),FF}.

其中分幾種情況
1、列表為空,則返回空佇列
2、列表只有一個元素時放入In,兩個元素時,按序放入Out、In
3、元素數量>=3,則將列表根據列表長度進行分割,分割成In、Out列表

queue:in(X, {In,Out})-> queue | badarg

將元素放在佇列尾部,存元素X時將元素放進In列表中([X|In]),當Out為空時則將In替換Out,這樣效率會更高,因為佇列是先進先出的,當Out不是空列表取Out列表第一個元素即可

queue:in_r(X, Queue)-> queue | badarg

與queue:in類似,不過是將元素放在佇列頭部。關於從佇列中獲取元素還有get、get_r、peek、peek_r這幾個方法都是從佇列中獲取元素,但是不會返回新的佇列

queue:out({In,Out})

我在原始碼上加了註釋,由以下原始碼,很清晰的可以看出佇列是怎麼取出元素的

-spec out(Q1 :: queue(Item)) ->
                 {{value, Item}, Q2 :: queue(Item)} |
                 {empty, Q1 :: queue(Item)}.
out({[],[]}=Q) ->
    {empty,Q};
out({[V],[]}) ->
    {{value,V},{[],[]}};
out({[Y|In],[]}) ->
    [V|Out] = lists:reverse(In, []),  %% 反轉後下次取元素直接取Out的頭元素
    {{value,V},{[Y],Out}};
out({In,[V]}) when is_list(In) ->     %% 取完Out為空時,呼叫r2f(),作用是將In的一半元素截取出來反轉形成Out,下次取元素就很方便
    {{value,V},r2f(In)};
out({In,[V|Out]}) when is_list(In) -> %% 直接從Out中取出頭元素,它一定是最早進去的
    {{value,V},{In,Out}};
out(Q) ->
    erlang:error(badarg, [Q]).

queue:out_r(Queue) 與queue:out類似,不過取出來的是尾部元素

queue:member(X, Queue) -> boolean | badarg

佇列是否包含此元素,通過判斷兩個列表是否包含此元素實現

queue:drop(Queue) -> queue | badarg

刪除佇列第一個元素並返回新的佇列
queue:drop_r(Queue) -> queue | badarg 則是刪除佇列最後一個元素並返回新的佇列

queue:reverse(Queue) -> queue | badarg

將佇列反轉,實現方式是Queue = {In, Out}, NewQueue = {Out, In}

queue:join(Queue1, Queue2) -> queue | badarg

合併兩個佇列
在這裡插入圖片描述

最後

如果需求是需要按照順序先進先出的取出資料,用佇列是很高效的