我需要将排序列表合并到一个列表中(列表的数量可能会有所不同)。当我刚接触 Erlang - 我不知道 pretty function 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 秒给我留下了深刻的印象。对比 21.676 秒。我的功能运行非常缓慢。
我认为使用匿名函数会降低性能,但摆脱fun
它并没有帮助。
你能指出我在哪里犯了主要错误吗?或者为什么模块列表中的函数要快得多?
谢谢