erlang 实现并行奇偶排序

-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]).


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值