【问题标题】:Erlang Bubble sortErlang 冒泡排序
【发布时间】:2011-08-04 19:06:54
【问题描述】:

我正在学习 Erlang 并决定在其中实现冒泡排序,我花了一些功夫,结果我成功了,但我发现我的思维方式不正确,有没有更有效的方法来实现它或不是吗?

bubble_sort(L) ->
if 
length(L) > 1 ->
    SL=bubble_sort_p(L),
    bubble_sort(lists:sublist(SL,1,length(SL)-1)) ++ [lists:last(SL)];
true -> L
end.

bubble_sort_p([]) -> [];    
bubble_sort_p([F | R]) ->
    case length(R) > 0 of
        true -> case F > hd(R) of
                true ->  [hd(R)] ++ bubble_sort_p([F|tl(R)]);
                false -> [F] ++ bubble_sort_p([hd(R)|tl(R)])
            end;
        false -> [F]
    end.

【问题讨论】:

  • ...提交了一个不完整的问题
  • 对不起,我不小心提交了,现在更正
  • 您的if length(L) > 1 会破坏性能。它必须遍历整个列表。你最好在空列表上进行模式匹配,然后单独处理它。在函数式语言中,合并排序通常是一个更好的主意。它速度更快,并且可以轻松地以稳定/流畅的方式编写,但它比您这里的要快得多。

标签: erlang bubble-sort


【解决方案1】:

我的想法是:

bubble_sort(L) -> bubble_sort(L, [], false).

bubble_sort([A, B | T], Acc, _) when A > B ->
  bubble_sort([A | T], [B | Acc], true);
bubble_sort([A, B | T], Acc, Tainted) ->
  bubble_sort([B | T], [A | Acc], Tainted);
bubble_sort([A | T], Acc, Tainted) ->
  bubble_sort(T, [A | Acc], Tainted);
bubble_sort([], Acc, true) ->
  bubble_sort(lists:reverse(Acc));
bubble_sort([], Acc, false) ->
  lists:reverse(Acc).

如果我们谈论效率,我们显然不应该首先使用冒泡排序。

【讨论】:

  • 对我来说很难读,但回答很有趣,效率与这个话题无关
  • Ok.. ;) 真正掌握函数式编程的关键之一是能够遵循递归模式。这实际上不是按书本的冒泡排序,因为 [A,B|T] 将继续 [A|T] 并将 B 放入结果中。这意味着只要 A 更大,A 就会在同一个通道中继续在列表中移动。哦,我想你说“有没有更有效的方法来实现它?”在 Q.. :)
  • 效率是指更少的代码行数,而不是算法效率:)
【解决方案2】:

请允许我以更易读的方式重新编写您的代码(无需更改任何语义):

bubble_sort(L) when length(L) =< 1 ->
    L;
bubble_sort(L) ->
    SL = bubble_sort_p(L),
    bubble_sort(lists:sublist(SL,1,length(SL)-1)) ++ [lists:last(SL)].

bubble_sort_p([])  ->
    [];
bubble_sort_p([F]) ->
    [F];
bubble_sort_p([F,G|T]) when F > G ->
    [G|bubble_sort_p([F|T])];
bubble_sort_p([F,G|T]) ->
    [F|bubble_sort_p([G|T])].

这应该可以更容易地思考程序中实际发生的事情。

【讨论】:

  • bubble_sort_p([F,G|T]) 当 G
  • 此答案并非旨在成为实际的“答案”,而是帮助寻找替代方法。它的可读性要好得多,因此对于可能想要检查算法“效率”的人来说应该不会那么头疼。尽管我不知道“高效”和“冒泡排序”会如何最终出现在同一个句子中,除了“冒泡排序效率不高,请使用更好的算法”。
【解决方案3】:

并雇用lists:foldr

bubble(List) ->
    Step = fun
              (E,{S,[]}) -> {S,[E]};
              (E,{_,[X|XS]}) when E > X -> {swapped,[X|[E|XS]]};
              (E,{S,XS}) -> {S,[E|XS]}
           end,
    case lists:foldr(Step, {intact,[]}, List) of
        {intact,XS} -> XS;
        {swapped,XS} -> bubble(XS)
    end.

【讨论】:

    【解决方案4】:

    http://en.literateprograms.org/Bubble_sort_%28Erlang%29有答案

    -module(bubblesort).
    -export([sort/1]).
    -import(lists, [reverse/1]).
    
    sort(L) -> sort(L, [], true).
    sort([], L, true) -> reverse(L);
    sort([], L, false) -> sort(reverse(L), [], true);
    sort([ X, Y | T ], L, _) when X > Y ->
    sort([ X | T ], [ Y | L ], false);
    sort([ X | T ], L, Halt) -> sort(T, [ X | L ], Halt).
    

    对 2,4,3,5,1 进行排序的示例

    排序([2,4,3,5,1])

    第一轮

    => 排序([2,4,3,5,1], [], true)

    => 排序([4,3,5,1], [2], true)

    => 排序([4,5,1], [3,2], false)

    => 排序([5,1], [4,3,2], false)

    => 排序([5], [1,4,3,2], false)

    => 排序([], [5,1,4,3,2], false)

    => 排序([2,3,4,1,5], [], true)

    第二轮

    => 排序([3,4,1,5], [2], true)

    => 排序([4,1,5], [3,2], true)

    => 排序([4,5], [1,3,2], false)

    => 排序([5], [4,1,3,2], false)

    => 排序([], [5,4,1,3,2], false)

    => 排序([2,3,1,4,5], [], true)

    第三轮

    => 排序([3,1,4,5], [2], true)

    => 排序([3,4,5], [1,2], false)

    => 排序([4,5], [3,1,2], false)

    => 排序([5], [4,3,1,2], false)

    => 排序([], [5,4,3,1,2], false)

    => 排序([2,1,3,4,5], 真)

    第四轮

    => 排序([2,3,4,5], [1], false)

    => 排序([3,4,5], [2,1], false)

    => 排序([4,5], [3,2,1], false)

    => 排序([5], [4,3,2,1], false)

    => 排序([], [5,4,3,2,1], false)

    => 排序([1,2,3,4,5], [], true)

    第五轮

    => 排序([2,3,4,5], [1], true)

    => 排序([3,4,5],[2,1], 真)

    => 排序([4,5],[3,2,1], 真)

    => 排序([5],[4,3,2,1], 真)

    => 排序([], [5,4,3,2,1], 真)

    => [1,2,3,4,5]

    【讨论】:

      【解决方案5】:
      -module(bubbleSort).
      -compile(export_all).
      -include_lib("eunit/include/eunit.hrl").
      
      sort(L) ->
          sort(L, length(L), []).
      
      sort(_L, 0, _Res) -> [];
      sort([H | _T], 1, Res) -> [H | Res];
      sort(L, Len, Res) ->
          T1 = lists:sublist(L, 1, Len),
          T2 = inner_sort(T1, []),
          Last = lists:last(T2),
         sort(T2, Len - 1, [Last | Res]).
      
      inner_sort([A, B], Res) when (A < B)->
          Res ++ [A, B];
      inner_sort([A, B], Res) ->
          Res ++ [B, A];
      inner_sort([A, B | T], Res) when (A < B) ->
          inner_sort([B | T], Res ++ [A]);
      inner_sort([A, B | T], Res) ->
          inner_sort([A | T], Res ++ [B]).
      
      test()->
          L = [5, 3, -1, 10, 6, 100, 99],
          ?assert(sort([])  =:= []),
          ?assert(sort([1]) =:= [1]),
          ?assert(sort([1, 2, 3, 4]) =:= [1, 2, 3, 4]),
          ?assert(sort([10, 5, 3, 2, 1]) =:= [1, 2, 3, 5, 10]),
          ?assert(sort(L) =:= [-1, 3, 5, 6, 10, 99, 100]).
      

      【讨论】:

        【解决方案6】:

        易于阅读和理解升序排序方向的实现。 采用尾递归,计算复杂度和内存使用是经典的。

        bsort([]) ->    [];
        bsort([H|T]) ->         bsort([H|T],[]).
        
        bsort([],[]) ->                 [];
        bsort([],[H|T]) ->      [H|T];
        bsort([A|B], Sorted) when is_list(Sorted) ->    M = lists:max([A|B]),   bsort([A|B] -- [M], [M] ++ Sorted).
        

        【讨论】:

          猜你喜欢
          • 2013-10-09
          • 2015-09-12
          • 1970-01-01
          • 2014-03-26
          • 2015-03-06
          • 2018-04-18
          • 2018-11-13
          • 2016-10-15
          • 1970-01-01
          相关资源
          最近更新 更多