相信大家都聽說過楊輝三角、選擇排序、集合交與並操作,本文就是用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.
求集合的交合並操作比較簡單,交操作主要步驟如下:
- 調用lists:sort/1對兩個列表進行排序;
- 若列表L1或列表L2為空,返回Ret,否則進入第三步;
- 將兩個列表L1、L2首元進行比較,分三種情況,首元相等、大於、小於依次處理。
並操作與交類似,只是在L1或L2為空時將不空的列表並入結果集Ret中,就不再詳細說其步驟了。
好了,這次的學習討論就到這了,這三個程序還是比較簡單的,關鍵是思路要清晰,其次是要以Erlang的角度來思考問題,那么用Erlang實現這三個程序就顯得簡單了。接下去,我還是會探討一些小程序,不過,我將花幾個專題專門討論Erlang中並行算法的實現,主要是並行枚舉排序、並行快速排序、PSRS排序等,也算是這個實戰系列最難得一部分吧,多謝大家的支持。
注:如無特殊說明,本博客內容純屬原創,轉載請注明:http://www.cnblogs.com/itfreer/ | IT閑人,謝謝!