我从您的查询中假设您都希望最大化队列的长度并获得所有值的总和.
首先回答你最简单的问题:Erlang队列,但是你希望代表它们,是正常的Erlang数据结构,因此将它们存储在字典中没有问题.
OTP queue模块实际上非常简单,但过多的接口很容易让人感到困惑.@ Nathon的入队函数可以通过不queue直接使用数据结构,而是通过定义自己的数据结构(包括队列及其当前长度)来提高效率{Length,Queue}.如果总和很重要,那么你甚至可以包括它.
队列表示非常简单,因此很容易编写自己的专用形式.
最简单的方法是将队列保留在列表中并从头部获取元素并将新元素添加到末尾.所以:
new(Max) when is_integer(Max), Max > 0 -> {0,Max,[]}. %Length, Max and Queue list
take({L,M,[H|T]}) -> {H,{L-1,M,T}}.
add(E, {L,M,Q}) when L < M ->
{L+1,M,Q ++ [E]}; %Add element to end of list
add(E, {M,M,[H|T]}) -
{M,M,T ++ [E]}. %Add element to end of list
Run Code Online (Sandbox Code Playgroud)
当队列变满时,将丢弃位于队列前面的最旧成员.空队列会生成错误.这是一个非常简单的结构,但由于每次添加新元素时都会复制队列,因此效率很低.反转列表没有用,因为每次从中删除元素时都会复制列表.但它很简单,而且确实有效.
一种更有效的结构是将队列分成两个列表,即队列的前端和队列的后端.后端相反,当前部空了时成为新的前部.所以:
new(Max) when is_integer(Max), Max > 0 ->
{0,Max,[],[]}. %Length, Max, Rear and Front
take({L,M,R,[H|T]}) -> {H,{L-1,M,R,T}};
take{{L,M,R,[]}) when L > 0 ->
take({L,M,[],lists:reverse(R)}). %Move the rear to the front
add(E, {L,M,R,F}) when L < M ->
{L+1,M,[R|E],F}; %Add element to rear
add(E, {M,M,R,[H|T]}) ->
{M,M,[R|E],T}; %Add element to rear
add(E, {M,M,R,[]}) ->
add(E, {M,M,[],lists:reverse(R)}). %Move the rear to the front
Run Code Online (Sandbox Code Playgroud)
同样,当队列变满时,位于队列前面的最旧成员将被删除,空队列将生成错误.这是queue模块中使用的数据结构.
将元素的当前总和添加到结构并直接管理它将非常容易.
通常,在处理这样的简单数据结构时,滚动自己的模块就像使用提供的模块一样容易.