Установка ограничения на размер очереди - PullRequest
1 голос
/ 29 ноября 2010

Как установить очередь для хранения N значений.Когда N достигнуто, удалите последний элемент и добавьте значение в начало очереди.

Должно ли это быть сделано с помощью оператора if?

Я также хочу вычислить значения в очереди при добавлении нового элемента.например, добавить все значения в очередь.

Ответы [ 2 ]

6 голосов
/ 30 ноября 2010

Из вашего запроса я предполагаю, что вы оба хотите максимизировать длину очереди и получить сумму всех значений.

Сначала ответьте на свой самый простой вопрос: очереди Erlang, однако вы хотите их представитьявляются обычными структурами данных Erlang, поэтому нет проблем с их сохранением в словаре.

Модуль OTP queue на самом деле очень прост, но множество интерфейсов легко запутывает его использование.Функция постановки @ Натона может быть значительно более эффективной, если не использовать непосредственно структуру данных 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

Когда очередь заполняется, самый старый элемент, находящийся в начале очереди, удаляется.Пустая очередь генерирует ошибку.Это очень простая структура, но она неэффективна, поскольку очередь копируется при каждом добавлении нового элемента.Изменение списка не помогает, так как тогда список копируется каждый раз, когда элемент удаляется из него.Но это просто, и это работает.

Гораздо более эффективная структура состоит в том, чтобы разделить очередь на два списка: внешний конец очереди и задний конец очереди.Задний конец полностью изменен и становится новым фронтом, когда фронт пуст.Итак:

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

Снова, когда очередь заполняется, самый старый элемент, находящийся в начале очереди, удаляется, и пустая очередь выдает ошибку.Это структура данных, используемая в модуле queue.

Было бы очень легко добавить текущую сумму элементов в структуру и управлять ею напрямую.

Часто при работедля таких простых структур данных, как этот, так же просто свернуть свой собственный модуль, как и для использования предоставленного.

4 голосов
/ 29 ноября 2010

Учитывая комментарии, это будет сделано:

enqueue(Value, Queue) ->
    Pushed = queue:in(Value, Queue),
    Sum = fun (Q) -> lists:sum(queue:to_list(Q)) end,
    case queue:len(Pushed) of
        Len when Len > 10 ->
            Popped = queue:drop(Pushed),
            {Popped, Sum(Popped)};
        _ ->
            {Pushed, Sum(Pushed)}
    end.

Если вы на самом деле не хотите суммировать элементы, вы можете вместо этого использовать lists:foldl или просто написать функцию для выполнения операциипрямо в очередь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...