Erlang -奇偶并行排序

-module (exe9).  
-export ([start/2,handle/4]).  
% L=[2,12,14,25,31,42,43,43,13,34,34,41,41,312,352,354].


% 将数据分给各个进程,并创建  
nodecreater([],Pids,M,Id,Master) ->
                                 io:format("Pids:~w Id:~w Master:~w~n",[Pids,Id,Master]),
                                 lists:reverse(Pids);  
nodecreater([Hlist|TLists],Pids,M,Id,Master) -> 
    io:format("Pids:~w Id:~w Master:~w~n",[Pids,Id,Master]), 
    Pid = spawn(?MODULE,handle,[Hlist,M,Id,Master]),  
    nodecreater(TLists,[Pid|Pids],M,Id+1,Master).  


% 迭代交换奇偶数据 
% 策略:当M是偶数时,Id 为奇数时,此core从他后面的core接受数据,再进行排序,再将结果等分成两部分,并将后半部分返回给
%      发送者,发送者接收到数据后进入下轮迭代,本核进入下一轮迭代。
%      当M是奇数时,Id=1或者Id=Core数时,直接进入下一轮。
%                 id为偶数时时(除去id为1和core数时),此core从他后面的core接受数据,再进行排序,再将结果等分成两部分,并将后半部分返回给
%                 发送者,发送者接收到数据后进入下轮迭代,本核进入下一轮迭代
% 
loop(Data,1,Id,_FrontPid,_NextPid,CoreN) ->
                                     io:format("Id:~w Res:~w ~n",[Id,Data]),
                                     Data;
loop(Data,M,Id,FrontPid,NextPid,CoreN) ->  
    io:format("Data:~w M:~w Id:~w ~n",[Data,M,Id]),
  if
      % M为偶数时
      M rem 2 =:= 0 -> 
                if 
                    %Id为奇数
                   Id rem 2 =:=1 -> 
                        receive {M,NewData,Nextid} ->
                            MergeData=lists:append(Data,NewData),
                            SortedData = lists:sort(MergeData),
                            LenPer=length(SortedData) div 2,
                            FrontData = lists:sublist(SortedData,LenPer),
                            TailData = lists:sublist(SortedData,LenPer+1,LenPer),
                            Nextid !{M,TailData,self()},
                            loop(FrontData,M-1,Id,FrontPid,Nextid,CoreN)

                        end;

                    %Id为偶数
                   true ->
                        FrontPid!{M,Data,self()},
                        receive {M,MyData,FrontPid} ->
                            loop(MyData,M-1,Id,FrontPid,NextPid,CoreN)
                        end

                end;
      true ->
                if
                   (Id =:= 1) or (Id =:= CoreN) -> 
                       loop(Data,M-1,Id,FrontPid,NextPid,CoreN);
                   true  ->
                        if
                            Id rem 2 =:= 0  ->
                            receive {M,NewData,Nextid} ->
                                MergeData=lists:append(Data,NewData),
                                SortedData = lists:sort(MergeData),
                                LenPer=length(SortedData) div 2,
                                FrontData = lists:sublist(SortedData,LenPer),
                                TailData = lists:sublist(SortedData,LenPer+1,LenPer),
                                Nextid !{M,TailData,self()},
                                loop(FrontData,M-1,Id,FrontPid,Nextid,CoreN)

                            end;

                            true -> FrontPid!{M,Data,self()},
                                receive {M,MyData,FrontPid} ->
                                 loop(MyData,M-1,Id,FrontPid,NextPid,CoreN)
                                 end
                        end
                end
  end.


handle(MyPart,M,Id,Master) ->  

    % 对自己分的的数据进行排序  
    MyData = lists:sort(MyPart),  
    io:format("handle Id:~w Data:~w ~n",[Id,MyData]),
    % 得到该进程后面进程的Id  
    receive  
        {next,NextPid} ->  
        NextPid  
    end,  
    % 得到该进程前面进程的Id  
    receive  
        {front,FrontPid} ->  
        FrontPid  
    end,    
    % 进行M次迭代  
    Res = loop(MyData,M,Id,FrontPid,NextPid,M),  
    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).  
sendgon([],ItsNextid,Ownid) ->   
    %io:format("Ownid:~w NextPid:~w~n",[Ownid,ItsNextid]),
    Ownid ! {next,ItsNextid};  
sendgon([Nextid|Pids],ItsNextid,Ownid) ->  
    %io:format("Ownid:~w NextPid:~w~n",[Ownid,ItsNextid]),
    Ownid ! {next,ItsNextid},  
    sendgon(Pids,Ownid,Nextid). 

% 使进程知道它前面的进程是什么
sendfrontid([Firstid|NewPids]) ->  
    sendgof(NewPids,Firstid,Firstid).  
sendgof([],ItsFrontid,Ownid) -> 
    %io:format("Ownid:~w FrontPid:~w~n",[Ownid,ItsFrontid]),  
    Ownid ! {front,ItsFrontid};  
sendgof([Nextid|Pids],ItsFrontid,Ownid) -> 
    %io:format("Ownid:~w FrontPid:~w~n",[Ownid,ItsFrontid]),  
    Ownid ! {front,ItsFrontid},  
    sendgof(Pids,Ownid,Nextid).  

%将Data分成M份
divlist(Data,M)->
    Len = length(Data),
    PerLen = Len div M,
    prodiv(Data,PerLen,M,[]).

prodiv(Data,PerLen,1,L) ->lists:reverse([Data|L]);

prodiv(Data,PerLen,M,L) ->
    Len=length(Data),
    Sub = lists:sublist(Data,PerLen),
    Res = lists:sublist(Data,PerLen+1,Len-PerLen),
    prodiv(Res,PerLen,M-1,[Sub|L]).

start(Data,M) ->   
    % 均匀划分  
    [FirstPart|PartLists] = divlist(Data,M),  
    io:format("after div:~n~w~n",[[FirstPart|PartLists]]),

    % 创建其他辅助进程  
    Pids = nodecreater(PartLists,[],M,2,self()), 
    io:format("Pids:~w~n",[Pids]),


    sendnextid([self()|Pids]),  
    sendfrontid([self()|Pids]),  

    % 主线程的ID为1,对自己的数据进行处理. 
    MyData = lists:sort(FirstPart),  
    receive  
        {next,NextPid} ->  
        NextPid  
    end,  
    receive  
        {front,FrontPid} ->  
        FrontPid  
    end,  

    FirstRes = loop(MyData,M,1,FrontPid,NextPid,M),  

    Result = merge_inorder(Pids,FirstRes),  
    io:format("~w~n",[Result]).  

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。