[erlang-questions] How can I implement a priority queue with Erlang?

Jeffrey Chen bitcowboy@REDACTED
Thu Aug 30 14:33:31 CEST 2007


I'm trying to implement a priority queue using heap struct. But I
can't do that efficient. Can anybody help me? I'll post my code below.
Thanks.


CODE:
exchange([], _, _, _, _, _) ->
    [];
exchange([_ | Rest], IndexA, ValueA, IndexB, ValueB, Index) when
IndexA == Index ->
    [ValueB | exchange(Rest, IndexA, ValueA, IndexB, ValueB, Index + 1)];
exchange([_ | Rest], IndexA, ValueA, IndexB, ValueB, Index) when
IndexB == Index ->
    [ValueA | exchange(Rest, IndexA, ValueA, IndexB, ValueB, Index + 1)];
exchange([Head | Rest], IndexA, ValueA, IndexB, ValueB, Index) ->
    [Head | exchange(Rest, IndexA, ValueA, IndexB, ValueB, Index + 1)].


%%% Heap %%%

max_heapify(Heap, Index) when Index * 2 > length(Heap) ->
    Heap;
max_heapify(Heap, Index) ->
    IndexValue = lists:nth(Index, Heap),

    LeftIndex  = 2 * Index,
    LeftValue  = lists:nth(LeftIndex, Heap),

    if
        2 * Index + 1 > length(Heap) ->
            RightIndex = LeftIndex,
            RightValue = LeftValue;
        true ->
            RightIndex = 2 * Index + 1,
            RightValue = lists:nth(RightIndex, Heap)
    end,

    if
        LeftValue > IndexValue, LeftValue >= RightValue ->
            LargestIndex = LeftIndex,
            LargestValue = LeftValue;
        RightValue > IndexValue, RightValue >= LeftValue ->
            LargestIndex = RightIndex,
            LargestValue = RightValue;
        true ->
            LargestIndex = Index,
            LargestValue = IndexValue
    end,

    if
        LargestIndex /= Index ->
            NewHeap = exchange(Heap, Index, IndexValue, LargestIndex,
LargestValue, 1),
            max_heapify(NewHeap, LargestIndex);
        true ->
            Heap
    end.

build_heap(L, 0) ->
    L;
build_heap(L, Index) ->
    NewL = max_heapify(L, Index),
    build_heap(NewL, Index - 1).

make_heap([]) ->
    [];
make_heap(L) ->
    build_heap(L, trunc(length(L) / 2)).

heap_pop([Head | Rest]) when  length(Rest) == 0 ->
    {Head, []};
heap_pop([Head | Rest]) ->
    {RestBody, RestTail} = lists:split(length(Rest) - 1, Rest),
    {Head, max_heapify(RestTail ++ RestBody, 1)}.

test_heap_pop([]) ->
    done;
test_heap_pop(Heap) ->
    {P, H} = heap_pop(Heap),
    io:format("~w, ~w~n", [P, H]),
    test_heap_pop(H).

adjust_heap_node(Heap, Index) when trunc(Index / 2) == 0 ->
    Heap;
adjust_heap_node(Heap, Index) ->
    IndexValue = lists:nth(Index, Heap),
    ParentIndex = trunc(Index / 2),
    ParentValue = lists:nth(ParentIndex, Heap),

    if
        IndexValue > ParentValue ->
            NewHeap = exchange(Heap, Index, IndexValue, ParentIndex,
ParentValue, 1),
            adjust_heap_node(NewHeap, ParentIndex);
        true ->
            Heap
    end.

heap_push(Heap, Push) ->
    adjust_heap_node(Heap ++ [Push], length(Heap) + 1).

-- 
Victory won't come to me, unless I go to it.



More information about the erlang-questions mailing list