ソートされたリストを1つのリストにマージする必要がありました(リストの数は異なる場合があります)。私はErlangを初めて使用するので、かなりの機能について知りませんでしたlists:merge/1
。そこで、独自のmerge/1
関数を実装しました。複雑さはO(m * n)(m-リストの数、n-リスト内の要素の平均数)であり、末尾再帰を使用します。これが私の関数です:
-module( merge ).
-export( [ merge/1 ] ).
merge( ListOfLists ) ->
merge( ListOfLists, [] ).
merge( [], Merged ) ->
lists:reverse( Merged );
merge( ListOfLists, Merged ) ->
[ [ Hfirst | Tfirst ] | ListOfLists_Tail ] = ListOfLists,
% let's find list, which has minimal value of head
% result would be a tuple { ListWithMinimalHead, Remainder_ListOfLists }
{ [ Hmin | Tmin ], ListOfLists_WithoutMinimalHead } =
lists:foldl(
fun( [ Hi | Ti ] = IncomingList, { [ Hmin | Tmin ], Acc } ) ->
case Hi < Hmin of
true ->
% if incoming list has less value of head then swap it
{ [ Hi | Ti ], [ [ Hmin | Tmin ] | Acc ] };
false ->
{ [ Hmin | Tmin ], [ IncomingList | Acc ] }
end
end,
{ [ Hfirst | Tfirst ], [] },
ListOfLists_Tail ),
% add minimal-valued head to accumulator, and go to next iteration
case Tmin == [] of
true ->
merge( ListOfLists_WithoutMinimalHead, [ Hmin | Merged ] );
false ->
merge( [ Tmin | ListOfLists_WithoutMinimalHead ], [ Hmin | Merged ] )
end.
しかし、私が知った後、私lists:merge/1
は自分のソリューションのパフォーマンスをテストすることにしました。
結果は次のとおりです。
1> c(merge).
{ok,merge}
2>
2>
3> timer:tc( lists, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,5) ] ] ).
{5,[1,1,1,1,1,2,2,2,2,3,3,3,4,4,5]}
3>
3> timer:tc( merge, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,5) ] ] ).
{564,[1,1,1,1,1,2,2,2,2,3,3,3,4,4,5]}
4>
4>
4> timer:tc( lists, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,100) ] ] ).
{2559,
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1|...]}
5>
5> timer:tc( merge, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,100) ] ] ).
{25186,
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1|...]}
6>
6>
6> timer:tc( lists, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,1000) ] ] ).
{153283,
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1|...]}
7>
7> timer:tc( merge, merge, [ [ lists:seq(1,N) || N <- lists:seq(1,1000) ] ] ).
{21676268,
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1|...]}
8>
0.153秒で感動しました。vs21.676秒 私の関数は非常に遅く動作します。
匿名関数を使用するとパフォーマンスが低下すると思いましたが、削除しても効果はありfun
ません。
私が主な間違いをした場所を教えていただけますか?または、なぜモジュールリストからの関数が非常に高速なのですか?
ありがとう