Erlang實戰:楊輝三角、選擇排序、集合交與並


  相信大家都聽說過楊輝三角、選擇排序、集合交與並操作,本文就是用Erlang語言實現這三個有趣的程序,相信大家都知道這三個概念,那么正式我們的erlang實戰之旅吧!

  實戰1:輸出楊輝三角:接口為start(N),N為行數。

-module(triangle).
-export([start/1]).

start(N) -> 
    L=getN(N), %% 獲取第楊輝三角第N行元素列表
    if
        N =:= 1 ->  %% N=1,直接輸出第一行,遞歸調用結束
            output(L);
        N =/= 1 -> %% N>1,遞歸調用start,先輸出第N-1行
            start(N-1),
            output(L)
    end.
            
%% 控制輸出第N行,列表L保存第N行元素,楊輝三角第N行有N個元素
output(L) -> output(L,1).
    
output(L,No) ->
    if 
        length(L) =:= No ->  
            io:format("~p~n",[lists:nth(length(L), L)]);
        length(L) =/= No ->
            io:format("~p,",[lists:nth(No,L)]),
            output(L,No+1)
    end.


getN(N) ->
    if
        N =:= 1 ->
            [1];
        N =:= 2 ->
            [1,1];
        N > 2  ->
            L = getN(N-1), %%獲得第N-1行元素
            process(L)   %% 通過第N-1行元素,推導出第N行
    end. 

process(Ele) -> process(Ele,1,[]).
    
process(Ele,No,L) ->
    Len = length(Ele)+1,
    if
        Len =:= No ->
            Temp = [1|L],
            lists:reverse(Temp);
        Len =/= No ->
            if
                No =:=1 ->
                    process(Ele,No+1,[No | L]);
                No =/=1 ->
                    E1 = lists:nth(No-1,Ele),
                    E2 = lists:nth(No,Ele),
                    process(Ele,No+1,[E1+E2 | L])
            end
    end. 

  在程序中主要部分我都作了注釋,這完全是按照我的想法來寫的,如果大家對程序比較苛刻的話,自己回去再精煉一下吧。在Windows下運行結果如下:

  實戰2:選擇排序:接口為sort(L)L為輸入數組。

    要求:給定一個無序數組,用選擇排序法進行排序(從小到大),要求將中間過程的每一步都輸出。

    原理:首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此類推,直到所有元素均排序完畢。

  程序代碼如下:

-module(choose_sort).
-export([sort/1]).

sort(L) -> sort(L,[]).

sort([],Ret) ->
    io:format("Final:~p~nsort finished.",[Ret]);
sort(L,Ret) ->
    Min = findMin(L),
    Minimum = lists:nth(Min,L), 
    NewL = lists:delete(Minimum,L), %% 在L中刪除最小元素
    if
        length(Ret) =:= 0 ->
            Ele = [Minimum],
            io:format("No.~p sort:~p~n",[length(Ele),Ele]);
        length(Ret) =/= 0 ->
            %% 使用兩個列表逆置的操作是因為,要將一個元素插入列表尾
            %% 注:在Erlang中,將一個元素到列表頭很簡單,插入到列表尾好像不直接,因此我用了兩次逆置
            Temp = lists:reverse(Ret),
            Ele = lists:reverse([Minimum|Temp]),
            io:format("No.~p sort:~p~n",[length(Ele),Ele])
    end,
    sort(NewL,Ele).
    

%% 找到最小元素位置
findMin(L) -> findMin(L,1,1).

findMin(L,Start,Loc) ->
    Ele = lists:nth(Start,L),
    Minimum = lists:nth(Loc,L),
    if
        length(L) =:= Start ->
            if
                Ele < Minimum  ->
                    Start;
                Ele >= Minimum ->
                    Loc
            end;
        length(L) =/= Start ->
            if
                Ele < Minimum  ->
                    findMin(L,Start+1,Start);
                Ele >= Minimum ->
                    findMin(L,Start+1,Loc)
            end
    end.

  注:最初我的想法是在原列表L上進行選擇排序,但是,在原列表上進行選擇排序可能需要交換列表的兩個元素,在Erlang中,交換列表的兩個元素沒有直接的方法,因此,我的最初想法比較繁瑣。上述代碼思想:(1)從列表L中選擇最小元素,然后插入到結果列表Ret,;(2)將最小元素從L中刪除;(3)遞歸調用(1)知道L中元素為空,返回結果Ret為最終排序結果。

  程序運行結果如下:

實戰3:集合交與並操作。

  用列表表示集合,求兩個集合的交集和並集,例如[1,3,4,5]和[4,5,7,9,10]的交集為[4,5],並集為[1,3,4,5,7,9,10]。

  代碼如下:

  

-module(set).
-export([inter/2]).
-export([union/2]).

inter(L1,L2) ->
    S1 = lists:sort(L1),
    S2 = lists:sort(L2),
    inter(S1,S2,[]).

inter(S1,S2,Ret) ->
    Len1 = length(S1),
    Len2 = length(S2),
    Log = (Len1 =:=0) or (Len2 =:= 0),
    if
        Log =:= true ->
            lists:reverse(Ret);
        Log =/= ture ->
            F1 = lists:nth(1,S1),
            F2 = lists:nth(1,S2),
            if
                F1 =:= F2 ->
                    inter(lists:delete(F1,S1),lists:delete(F2,S2),[F1|Ret]);
                F1 < F2 ->
                    inter(lists:delete(F1,S1),S2,Ret);
                F1 > F2 ->     
                    inter(S1,lists:delete(F2,S2),Ret)
            end
    end.
        

union(L1,L2) ->
    S1 = lists:sort(L1),
    S2 = lists:sort(L2),
    lists:reverse(union(S1,S2,[])).

union(S1,S2,Ret) ->
    Len1 = length(S1),
    Len2 = length(S2),
    Log = (Len1 =/= 0) and (Len2 =/= 0),
    if
        Len1 =:= 0 ->
            lists:append(Ret,S2);
        Len2 =:=0  ->
            lists:append(Ret,S1);
        Log =:= true ->
            F1 = lists:nth(1,S1),
            F2 = lists:nth(1,S2),
            if
                F1 =:= F2 ->
                    union(lists:delete(F1,S1),lists:delete(F2,S2),[F1|Ret]);
                F1 =/= F2 ->
                    Temp = [F1|Ret],
                    Temp2 = [F2 | Temp],
                    union(lists:delete(F1,S1),lists:delete(F2,S2),Temp2)
            end
    end.

  求集合的交合並操作比較簡單,交操作主要步驟如下:

  1. 調用lists:sort/1對兩個列表進行排序;
  2. 若列表L1或列表L2為空,返回Ret,否則進入第三步;
  3. 將兩個列表L1、L2首元進行比較,分三種情況,首元相等、大於、小於依次處理。

  並操作與交類似,只是在L1或L2為空時將不空的列表並入結果集Ret中,就不再詳細說其步驟了。

  好了,這次的學習討論就到這了,這三個程序還是比較簡單的,關鍵是思路要清晰,其次是要以Erlang的角度來思考問題,那么用Erlang實現這三個程序就顯得簡單了。接下去,我還是會探討一些小程序,不過,我將花幾個專題專門討論Erlang中並行算法的實現,主要是並行枚舉排序、並行快速排序、PSRS排序等,也算是這個實戰系列最難得一部分吧,多謝大家的支持。

 

  注:如無特殊說明,本博客內容純屬原創,轉載請注明:http://www.cnblogs.com/itfreer/ | IT閑人,謝謝!

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM