洗牌算法(Shuffle)的Erlang实现

之前写了一片文介绍过等概率随机取数算法的几种实现(洗牌算法),Erlang并没有内置这种函数,现在补充下Erlang版本的实现。

方法一

给每个元素加一个随机的顺序id,然后进行排序。速度快,但是随机性差。

shuffle(L) ->
	List1 = [{random:uniform(), X} || X <- L],
	List2 = lists:keysort(1, List1),
	[E || {_, E} <- List2].

方法二 Knuth-Durstenfeld Shuffle算法

shuffle([]) ->
	[];
shuffle([_] = L) ->
	L;
shuffle(L) ->
	shuffle_1(1, L, erlang:length(L)).

shuffle_1(Len, L, Len) ->
	L;
shuffle_1(Cur, L, Len) ->
	S = Cur + erlang:round((Len - Cur) * random:uniform()),
    L2 = swap_element(L, Cur, S),
    shuffle_1(Cur + 1, L2, Len).

swap_element(L, N, N) ->
    L;
swap_element(L, N1, N2) ->
    Z = lists:zip(lists:seq(1, length(L)), L),
    {value, E1} = lists:keysearch(N1, 1, Z),
    {value, E2} = lists:keysearch(N2, 1, Z),
    Z2 = lists:keyreplace(N1, 1,
                    lists:keyreplace(N2, 1, Z, E1),
                    E2),
    {_, Result} = lists:unzip(Z2),
    Result.

算法详解可以看上方的链接,这个方法的随机性好,但是因为erlang的变量不可重复赋值,且List通过链表实现,导致效率比较低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值