6060 join /2 ,
6161 seq /2 , seq /3 ,
6262 sort /1 , sort /2 ,
63+ merge /2 , merge /3 ,
6364 split /2 ,
6465 usort /1 , usort /2 ,
6566 dropwhile /2 ,
@@ -622,7 +623,9 @@ join_1(_Sep, []) ->
622623% %-----------------------------------------------------------------------------
623624-spec seq (From :: integer (), To :: integer ()) -> list ().
624625seq (From , To ) when is_integer (From ) andalso is_integer (To ) andalso From =< To ->
625- seq_r (From , To , 1 , []).
626+ seq_r (From , To , 1 , []);
627+ seq (From , To ) when is_integer (From ) andalso is_integer (To ) andalso From =:= To + 1 ->
628+ [].
626629
627630% %-----------------------------------------------------------------------------
628631% % @param From from integer
@@ -644,6 +647,8 @@ seq(From, To, Incr) when
644647 error (badarg );
645648seq (To , To , 0 ) ->
646649 [To ];
650+ seq (From , To , Incr ) when From =:= To + Incr ->
651+ [];
647652seq (From , To , Incr ) ->
648653 Last = From + ((To - From ) div Incr ) * Incr ,
649654 seq_r (From , Last , Incr , []).
@@ -672,8 +677,23 @@ sort(List) when is_list(List) ->
672677% % @end
673678% %-----------------------------------------------------------------------------
674679-spec sort (Fun :: fun ((T , T ) -> boolean ()), List :: [T ]) -> [T ].
675- sort (Fun , List ) when is_function (Fun ), is_list (List ) ->
676- quick_sort (Fun , List ).
680+ sort (Fun , List ) when is_function (Fun , 2 ), is_list (List ) ->
681+ merge_sort (Fun , List ).
682+
683+ merge_sort (_Fun , []) ->
684+ [];
685+ merge_sort (_Fun , [_ ] = L ) ->
686+ L ;
687+ merge_sort (Fun , List ) ->
688+ {H1 , H2 } = merge_sort_split (List , List , []),
689+ merge (Fun , merge_sort (Fun , H1 ), merge_sort (Fun , H2 ), []).
690+
691+ merge_sort_split ([], Half1 , Half2 ) ->
692+ {lists :reverse (Half2 ), Half1 };
693+ merge_sort_split ([_ ], Half1 , Half2 ) ->
694+ {lists :reverse (Half2 ), Half1 };
695+ merge_sort_split ([_ , _ | T ], [H | Half1T ], Half2 ) ->
696+ merge_sort_split (T , Half1T , [H | Half2 ]).
677697
678698% %-----------------------------------------------------------------------------
679699% % @param N elements non negative Integer
@@ -708,14 +728,39 @@ split(N, [H | T], R) ->
708728split (_ , [], _ ) ->
709729 badarg .
710730
711- % % Attribution: https://erlang.org/doc/programming_examples/list_comprehensions.html#quick-sort
712- % % @private
713- quick_sort (Fun , [Pivot | T ]) ->
714- quick_sort (Fun , [X || X <- T , Fun (X , Pivot )]) ++
715- [Pivot ] ++
716- quick_sort (Fun , [X || X <- T , not Fun (X , Pivot )]);
717- quick_sort (_Fun , []) ->
718- [].
731+ % %-----------------------------------------------------------------------------
732+ % % @param List1 first list to merge, previously sorted
733+ % % @param List2 second list to merge, previously sorted
734+ % % @returns Merged list of List1 and List2
735+ % % @doc Returns a list formed by merging List1 and List2, following natural
736+ % % order. If elements compare equal, element from List1 is picked first
737+ % % @end
738+ % %-----------------------------------------------------------------------------
739+ merge (List1 , List2 ) ->
740+ merge (fun lt /2 , List1 , List2 , []).
741+
742+ % %-----------------------------------------------------------------------------
743+ % % @param Fun ordering function
744+ % % @param List1 first list to merge, previously sorted
745+ % % @param List2 second list to merge, previously sorted
746+ % % @returns Merged list of List1 and List2
747+ % % @doc Returns a list formed by merging List1 and List2, following Fun
748+ % % order. If elements compare equal, element from List1 is picked first
749+ % % @end
750+ % %-----------------------------------------------------------------------------
751+ merge (Fun , List1 , List2 ) ->
752+ merge (Fun , List1 , List2 , []).
753+
754+ merge (_Fun , [], Right , Acc ) ->
755+ lists :reverse (Acc , Right );
756+ merge (_Fun , Left , [], Acc ) ->
757+ lists :reverse (Acc , Left );
758+ merge (Fun , [A | As ], [B | Bs ], Acc ) ->
759+ % keep sort stable, if B < A, put it first, otherwise keep A first
760+ case Fun (B , A ) of
761+ true -> merge (Fun , [A | As ], Bs , [B | Acc ]);
762+ false -> merge (Fun , As , [B | Bs ], [A | Acc ])
763+ end .
719764
720765% % @private
721766lt (A , B ) -> A < B .
0 commit comments