标题:常见算法错误之随机洗牌算法
只看楼主
cacker
该用户已被删除
得分:0 
提示: 作者被禁止或删除 内容自动屏蔽
2011-01-15 22:23
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
得分:0 
以下是引用cacker在2011-1-15 22:22:37的发言:

我记得。我当时写斗地主    是随即出一个数  然后与数组最后一个数交换   然后每次随即范围减1

这样可以保证效率   但是貌似也挺正确啊    至于几率问题,没考虑过。能打乱牌的顺序就行

你这样写是对的,这种做法就是我在最后给出的代码的做法

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2011-01-15 22:27
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
得分:0 
说实话, 不太明白,
为什么从后往前交换是对的, 从前往后交换就是错的呢?

我就是真命天子,顺我者生,逆我者死!
2011-01-15 22:36
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
得分:0 
void shuffle(int* arr, int len)
{
    int n;
    for (n = 0; n < len; ++n)
    {
        int i = myrand(n); //生成一个 0 至 len-1之间的随机数,也可能写成 rand() % len
        SWAP(arr[n], arr[i], int); //交换arr[n]和arr[i]
    }
}
是不是这样就对了呢?

我就是真命天子,顺我者生,逆我者死!
2011-01-15 22:37
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
得分:0 
void shuffle(int* arr, int len)
{
    int n;
    for (n = 0; n < len; ++n)
    {
        int i = myrand(n);
        SWAP(arr[n], arr[i + n], int);
    }
}

这样也对,换个方向的写法

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2011-01-15 22:56
nbaqqqq
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:202
专家分:137
注 册:2009-11-6
得分:1 
#define SWAP(a, b, _t) do{_t t = a; a = b; b = t; }while(0)

怎么有这种写法?哪本书上的?求书名
2011-01-15 22:56
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
得分:0 
以下是引用nbaqqqq在2011-1-15 22:56:17的发言:

#define SWAP(a, b, _t) do{_t t = a; a = b; b = t; }while(0)

怎么有这种写法?哪本书上的?求书名
闲谈两句,
我发现一个问题,如果代码写的太过通用反而阻碍算法的学习,我个人建议代码要尽可能的简单,
并且在形式和逻辑上保持一致性。
所以,无关紧要的 typedef、define 最好直接无视掉

[ 本帖最后由 BlueGuy 于 2011-1-15 23:07 编辑 ]

我就是真命天子,顺我者生,逆我者死!
2011-01-15 23:01
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
得分:0 
以下是引用nbaqqqq在2011-1-15 22:56:17的发言:

#define SWAP(a, b, _t) do{_t t = a; a = b; b = t; }while(0)

怎么有这种写法?哪本书上的?求书名
这种写法只是我个人的喜好,你写成其它的形式也是可以的,这也不是从什么书里找的

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2011-01-18 00:01
找工作中
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:41
专家分:114
注 册:2008-5-21
得分:0 
以下是引用nbaqqqq在2011-1-15 22:56:17的发言:

#define SWAP(a, b, _t) do{_t t = a; a = b; b = t; }while(0)

怎么有这种写法?哪本书上的?求书名
这样写是为了让SWAP看上去像一个语句,因为最后会强制需要一个分号。
C++里面其实用模板更好,不过C语言没有。

lz最后那个算法,本质上就是做选取。也就是说,如果你有一堆牌,要打乱。那个错误的方法,就是在牌堆里面不停地交换,这样会导致分布不均。lz提供的正确的做法,本质上就是就是建立另一堆牌(最开始为空)
1.在牌堆里面随机抽一张,放在另一堆牌上
2.如牌堆不为空,goto 1
这样,最后得到的另一堆牌也是随机的,并且分布和n!相符合。

拿到工资先买个山寨手机
2011-02-14 16:23
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
得分:0 
向美琴老师学习了
2011-02-14 17:25



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-331122-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017772 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved