erlang 实现psrs 并行排序算法

-module (psrs).
-export ([start/2,handle/1]).

% 测试数据:psrs:start([15,46,48,93,39,6,72,91,14,36,69,40,89,61,97,12,21,54,53,97,84,58,32,27,33,72,20],3).

% 将数据分给各个进程,并创建
nodecreater([],Pids) -> Pids;
nodecreater([Hlist|TLists],Pids) ->
	Pid = spawn(?MODULE,handle,[Hlist]),
	nodecreater(TLists,[Pid|Pids]).

% 将列表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.


% 将进程号列表 告知 所有进程
sendpids(Pids,[H]) -> H ! {pids,Pids};	
sendpids(Pids,[H|T]) -> 
	H ! {pids,Pids},
	sendpids(Pids,T).

% 对数据进行采样
getsample(MyPart,M) ->
	Len = lists:flatlength(MyPart),
	PerLen = Len div M,
	getsamples(MyPart,PerLen,[]).

getsamples(MyPart,PerLen,T) ->
	[H|_T] = MyPart,
	Len = lists:flatlength(MyPart),
	if
		PerLen < Len ->
			NewData = lists:nthtail(PerLen,MyPart),
			getsamples(NewData,PerLen,[H|T]);
		true ->
			[H|T]
	end.

% 接收其他进程的样本
receivesample(0,Sample) -> Sample;
receivesample(M,Sample) ->
	receive
		{sample,OtherSample} ->
			receivesample(M-1,lists:append(Sample,OtherSample))
		end.

% 从选出的样本中找到新的样本
finditem(Data,M) ->
	Len = lists:flatlength(Data),
	PerLen = Len div (M+1),
	NewData = lists:sublist(Data,PerLen+1,Len-PerLen),
	finditems(NewData,PerLen,[]).
finditems(Data,PerLen,T) ->
	[H|_T] = lists:sublist(Data,PerLen),
	Len = lists:flatlength(Data),
	if
		PerLen <  Len ->
			NewData = lists:sublist(Data,PerLen+1,Len-PerLen),
			finditems(NewData,PerLen,[H|T]);
		true ->
			[H|T]
	end.


% 告知其他进程主元
sendItems(_Items,[]) -> sendItemsdone;
sendItems(Items,[Hid|Pids]) ->
	Hid ! {masteritems , Items},
	sendItems(Items,Pids).

% 按主元进行划分
partlist(MyPart,Items) ->
	parting(MyPart,Items,[]).
parting(LastPart,[],T) -> [LastPart|T];
parting(MyPart,[H|Items],T) ->
	{NewPart,LastPart} = {[X || X <- MyPart , X =< H],[X || X <- MyPart , X > H]},
	parting(LastPart,Items,[NewPart|T]).

% 全局交换列表,分成两步先发送完自己持有的列表,然后再开始接收
swap(Lists,Pids) ->
	swapsend(Lists,lists:reverse(Pids)),
	swapreceive(lists:flatlength(Pids),[]).
% 发送: 逐个取出各个列表和各个pid ,将对应列表发给对应进程
swapsend([],[]) -> swapdone;
swapsend([Hlist|NewpartList],[Hids|Pids]) ->
	Hids ! {otherlist,Hlist},
	swapsend(NewpartList,Pids).
% 接收
swapreceive(0,R) -> R;
swapreceive(M,R) ->
	receive
		{otherlist,Otherlist} ->
		swapreceive(M-1,[Otherlist|R])
	end.

% 对排好序的小列表的列表 进行归并排序
merge_sort(SortedLists) -> 
	NewList = listsappend(SortedLists,[]),
	lists:sort(NewList).
listsappend([],R) -> R;
listsappend([Hlist|SortedLists],R) ->
	listsappend(SortedLists,lists:append(R,Hlist)).
% 逐次给辅助进程发送输出信号
merge_inorder([],R) ->R;
merge_inorder([Hid|Pids],R) ->
	receive
		{result,Hid,Res} ->
		merge_inorder(Pids,lists:append(R,Res))
	end.


% 主进程 与辅助进程的区别 主要在采样 是由主进程做,以及其他协调工作
start(Data,M) -> 
	% 均匀划分
	[FirstPart|PartLists] = lists:reverse(divList(Data,M)),
	%io:format("~w~n",[FirstPart|PartLists]),
	% 创建其他辅助进程
	Pids = nodecreater(PartLists,[]),
	% 使全部进程都知道其他进程的进程号,后来的全局交换需要
	sendpids([self()|Pids],Pids),

	SortList = lists:sort(FirstPart),
	Sample = getsample(SortList,M),

	% 接收其他进程的样本,排序选出主元
	NewSample = receivesample(M-1,Sample),
	SortSample = lists:sort(NewSample),
	Items = lists:reverse(finditem(SortSample,M-1)),

	% 告知其他进程主元
	sendItems(Items,Pids),

	% 按主元进行划分
	NewpartList = partlist(FirstPart,Items),

	% 全局交换
	SortLists =  swap(NewpartList,[self()|Pids]),

	NewSortList = merge_sort(SortLists),

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

% 辅助进程
handle(MyPart) ->
	SortList = lists:sort(MyPart),

	% 接受其他进程的Pids
	receive
		{pids,PPids} -> 
		[Master|_Pids] = PPids
	end,
	M = lists:flatlength(PPids),

	% 找出样本
	Sample = getsample(SortList,M),

	% 向主进程发送样本
	Master ! {sample,Sample},

	% 接收主进程筛选出的主元
	receive
		{masteritems,Items} ->
		Items
	end,

	NewpartList = partlist(MyPart,Items),

	% 全局交换
	SortLists = swap(NewpartList,PPids),

	% 归并排序
	NewSortList =  merge_sort(SortLists),

	Master ! {result,self(),NewSortList}.


















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值