|
58 | 58 | join/2, |
59 | 59 | seq/2, seq/3, |
60 | 60 | sort/1, sort/2, |
| 61 | + merge/2, merge/3, |
61 | 62 | split/2, |
62 | 63 | usort/1, usort/2, |
63 | 64 | duplicate/2, |
@@ -650,8 +651,23 @@ sort(List) when is_list(List) -> |
650 | 651 | %% @end |
651 | 652 | %%----------------------------------------------------------------------------- |
652 | 653 | -spec sort(Fun :: fun((T, T) -> boolean()), List :: [T]) -> [T]. |
653 | | -sort(Fun, List) when is_function(Fun), is_list(List) -> |
654 | | - quick_sort(Fun, List). |
| 654 | +sort(Fun, List) when is_function(Fun, 2), is_list(List) -> |
| 655 | + merge_sort(Fun, List). |
| 656 | + |
| 657 | +merge_sort(_Fun, []) -> |
| 658 | + []; |
| 659 | +merge_sort(_Fun, [_] = L) -> |
| 660 | + L; |
| 661 | +merge_sort(Fun, List) -> |
| 662 | + {H1, H2} = merge_sort_split(List, List, []), |
| 663 | + merge(Fun, merge_sort(Fun, H1), merge_sort(Fun, H2), []). |
| 664 | + |
| 665 | +merge_sort_split([], Half1, Half2) -> |
| 666 | + {lists:reverse(Half2), Half1}; |
| 667 | +merge_sort_split([_], Half1, Half2) -> |
| 668 | + {lists:reverse(Half2), Half1}; |
| 669 | +merge_sort_split([_, _ | T], [H | Half1T], Half2) -> |
| 670 | + merge_sort_split(T, Half1T, [H | Half2]). |
655 | 671 |
|
656 | 672 | %%----------------------------------------------------------------------------- |
657 | 673 | %% @param N elements non negative Integer |
@@ -686,14 +702,39 @@ split(N, [H | T], R) -> |
686 | 702 | split(_, [], _) -> |
687 | 703 | badarg. |
688 | 704 |
|
689 | | -%% Attribution: https://erlang.org/doc/programming_examples/list_comprehensions.html#quick-sort |
690 | | -%% @private |
691 | | -quick_sort(Fun, [Pivot | T]) -> |
692 | | - quick_sort(Fun, [X || X <- T, Fun(X, Pivot)]) ++ |
693 | | - [Pivot] ++ |
694 | | - quick_sort(Fun, [X || X <- T, not Fun(X, Pivot)]); |
695 | | -quick_sort(_Fun, []) -> |
696 | | - []. |
| 705 | +%%----------------------------------------------------------------------------- |
| 706 | +%% @param List1 first list to merge, previously sorted |
| 707 | +%% @param List2 second list to merge, previously sorted |
| 708 | +%% @returns Merged list of List1 and List2 |
| 709 | +%% @doc Returns a list formed by merging List1 and List2, following natural |
| 710 | +%% order. If elements compare equal, element from List1 is picked first |
| 711 | +%% @end |
| 712 | +%%----------------------------------------------------------------------------- |
| 713 | +merge(List1, List2) -> |
| 714 | + merge(fun lt/2, List1, List2, []). |
| 715 | + |
| 716 | +%%----------------------------------------------------------------------------- |
| 717 | +%% @param Fun ordering function |
| 718 | +%% @param List1 first list to merge, previously sorted |
| 719 | +%% @param List2 second list to merge, previously sorted |
| 720 | +%% @returns Merged list of List1 and List2 |
| 721 | +%% @doc Returns a list formed by merging List1 and List2, following Fun |
| 722 | +%% order. If elements compare equal, element from List1 is picked first |
| 723 | +%% @end |
| 724 | +%%----------------------------------------------------------------------------- |
| 725 | +merge(Fun, List1, List2) -> |
| 726 | + merge(Fun, List1, List2, []). |
| 727 | + |
| 728 | +merge(_Fun, [], Right, Acc) -> |
| 729 | + lists:reverse(Acc, Right); |
| 730 | +merge(_Fun, Left, [], Acc) -> |
| 731 | + lists:reverse(Acc, Left); |
| 732 | +merge(Fun, [A | As], [B | Bs], Acc) -> |
| 733 | + % keep sort stable, if B < A, put it first, otherwise keep A first |
| 734 | + case Fun(B, A) of |
| 735 | + true -> merge(Fun, [A | As], Bs, [B | Acc]); |
| 736 | + false -> merge(Fun, As, [B | Bs], [A | Acc]) |
| 737 | + end. |
697 | 738 |
|
698 | 739 | %% @private |
699 | 740 | lt(A, B) -> A < B. |
|
0 commit comments