-module (jiousort).
-export ([start/2,handle/4]).
% 测试数据:jiousort:start([15,11,9,16,3,14,8,7,4,6,12,10,5,2,13,1],4).
% 将数据分给各个进程,并创建
nodecreater([],Pids,_M,_Id,_Master) -> Pids;
nodecreater([Hlist|TLists],Pids,M,Id,Master) ->
Pid = spawn(?MODULE,handle,[Hlist,M,Id,Master]),
nodecreater(TLists,[Pid|Pids],M,Id+1,Master).
% 将列表Data 分成M份均匀的子列表
divList(Data,M) ->
Len = lists:flatlength(Data),
PerLen = Len div M,
dividing(Data,PerLen,[]).
dividing(Data,PerLen,T) ->
Sublist = lists:sublist(Data, PerLen),
Len = lists:flatlength(Data),
if
PerLen < Len ->
NewData = lists:sublist(Data,PerLen+1,lists:flatlength(Data)-PerLen),
dividing(NewData,PerLen,[Sublist|T]);
true ->
[Sublist|T]
end.
% 迭代交换奇偶数据
loop(Data,0,_Id,_FrontPid,_NextPid) -> Data;
loop(Data,M,Id,FrontPid,NextPid) ->
A = M rem 2,
B = Id rem 2,
if
A =:= B ->
FrontPid ! {nextdata,Data,self()};
true ->
NextPid ! {frontdata,Data,self()}
end,
receive
{nextdata,OtherData,From} ->
if
From =:= self() ->
NewData = Data,
loop(NewData,M-1,Id,FrontPid,NextPid);
true ->
NewData = lists:sublist(lists:sort(Data++OtherData),1,length(Data)),
loop(NewData,M-1,Id,FrontPid,NextPid)
end;
{frontdata,OtherData,From} ->
if
From =:= self() ->
NewData = Data,
loop(NewData,M-1,Id,FrontPid,NextPid);
true ->
NewData = lists:sublist(lists:sort(Data++OtherData),length(OtherData)+1,length(Data)),
loop(NewData,M-1,Id,FrontPid,NextPid)
end
end.
handle(MyPart,M,Id,Master) ->
% 对自己分的的数据进行排序
MyData = lists:sort(MyPart),
% 得到该进程后面进程的Id
receive
{next,NextPid} ->
NextPid
end,
% 得到该进程前面进程的Id
receive
{front,FrontPid} ->
FrontPid
end,
% 进行M次迭代
Res = loop(MyData,M,Id,FrontPid,NextPid),
Master ! {result,self(),Res}.
% 逐次接收
merge_inorder([],R) ->R;
merge_inorder([Hid|Pids],R) ->
receive
{result,Hid,Res} ->
merge_inorder(Pids,lists:append(R,Res))
end.
% 使进程知道紧接其的后续进程pid
sendnextid(Pids) ->
[Firstid|NewPids] = lists:reverse(Pids),
sendgon(NewPids,Firstid,Firstid).
sendfrontid([Firstid|NewPids]) ->
sendgof(NewPids,Firstid,Firstid).
sendgon([],ItsNextid,Ownid) ->
Ownid ! {next,ItsNextid};
sendgon([Nextid|Pids],ItsNextid,Ownid) ->
Ownid ! {next,ItsNextid},
sendgon(Pids,Ownid,Nextid).
sendgof([],ItsFrontid,Ownid) ->
Ownid ! {front,ItsFrontid};
sendgof([Nextid|Pids],ItsFrontid,Ownid) ->
Ownid ! {front,ItsFrontid},
sendgof(Pids,Ownid,Nextid).
start(Data,M) ->
% 均匀划分
[FirstPart|PartLists] = lists:reverse(divList(Data,M)),
% 创建其他辅助进程
Pids = lists:reverse(nodecreater(PartLists,[],M,2,self())),
sendnextid([self()|Pids]),
sendfrontid([self()|Pids]),
% 对自己的数据进行处理
MyData = lists:sort(FirstPart),
receive
{next,NextPid} ->
NextPid
end,
receive
{front,FrontPid} ->
FrontPid
end,
FirstRes = loop(MyData,M,1,FrontPid,NextPid) ,
Result = merge_inorder(Pids,FirstRes),
io:format("~w~n",[Result]).
erlang 实现并行奇偶排序
最新推荐文章于 2021-05-14 04:45:35 发布