%% $Id: heapsort.erlang,v 1.0 2002/09/24 12:16:00 dada Exp $
%%
%% contributed by Isaac Gouy
%%
%% Quick and Dirty transliteration from the Mercury solution
%% with +1 adjustment for array indexes.
%% Mercury uses 0..N-1 and Erlang uses 1..N
%%
%% Usage: start from command line with
%% erlc heapsort.erl
%% erl -noinput -s heapsort main 10000
-module(heapsort).
-export([main/1]).
random_heap(I, Seed, H) ->
if
I < size(H) ->
{NextSeed, R} = gen_random(Seed),
random_heap(I+1, NextSeed, up_heap(I, R, H));
true -> H
end.
up_heap(N, Y, H) ->
HalfN = N div 2,
X = element(HalfN+1, H), %%%% +1
Condition = 0 < N andalso X < Y,
if
Condition -> up_heap(HalfN, Y, setelement(N+1, H, X)); %%%% +1
true -> setelement(N+1, H, Y) %%%% +1
end.
heapsort(0, H) -> H;
heapsort(N, H) -> heapsort(N-1, remove_greatest(N, H)).
remove_greatest(N, H) ->
X = element(0+1, H), %%%% +1
Y = element(N+1, H), %%%% +1
down_heap(0, N-1, Y, setelement(N+1, H, X)). %%%% +1
down_heap(I, N, X, H) ->
L = I + I + 1,
R = L + 1,
if
N < L ->
setelement(I+1, H, X); %%%% +1
true ->
Condition = R < N andalso element(R+1, H) > element(L+1, H), %%%% +1
J = if
Condition -> R;
true -> L
end,
Y = element(J+1, H),
if
X > Y -> setelement(I+1, H, X); %%%% +1
true -> down_heap(J, N, X, setelement(I+1, H, Y)) %%%% +1
end
end.
gen_random(Seed) ->
IM = 139968, IA = 3877, IC = 29573,
S = ((Seed * IA) + IC) rem IM,
{S, S/IM}.
main([Arg]) ->
N = list_to_integer(atom_to_list(Arg)),
Seed = 42,
RandomHeap = random_heap(0, Seed, erlang:make_tuple(N, 0.0)),
SortedHeap = heapsort(N-1, RandomHeap),
io:fwrite("~.10f~n", [element(N, SortedHeap)]),
halt(0).