• 洗牌算法分析


    洗牌问题:给定函数RandInt(a, b)(产生最小为a,最大为b的随机数), 将1,2,3,……54这54个整数顺序打乱,并且每个数出现的概率相等。

     
    这是《数据结构与算法分析》中的一道习题,习题中给出了三个算法思路(n=54):
    1. 按如下方法填入从a[0]到a[n-1]的数组A;为了填入a[i],生成随机数直到它不同于已经生成的a[0],a[1],……,a[i-1],再将其填入a[i];
    2. 同算法1,但是使用一个状态数组used[]来判断之前是否生成了该数,最初将一个随机数ran放入数组a时,将used[ran]=1,之后产生随机数时先查找used数组确定该随机数是否出现过,若没有,则将其加入数组;
    3. 初始化数组a[i]=i+1,然后倒序遍历数组a的同时swap(&a[i], &a[RandInt(0,i)]);
     
         第一种方法思路简单但是当N变大时运算量太大,方法2和1的思路相当,但是引入状态数组,降低了复杂度;方法3中,每次生成的是元素下标,只有元素交换,无赋值,所以不会产生重复的元素,可以理解为1/n的概率选一个元素交换到末尾,再以1/(n-1)的概率选剩下元素中的一个交换到倒数第二位,依次下去即可。下面是方法2和3的具体代码:
    /*方法2*/
    void
    randsort2(int n){ int a[n], used[n]; int i, t; for(i=0; i<n; i++) used[i]=0; srand(time(NULL)); for (i=0; i<n; i++){ while (1){ t=rand()%n; if (used[t] == 0){ used[t] = 1; a[i] = t+1; break; }else continue; } } // printarray(a, n); }
    /*方法3*/
    void
    randsort3(int n){ int a[n]; int i; for (i=0; i<n; i++) a[i] = i+1; for (i=n-1; i>0; i--){ int t = RandInt(0, i); swap(&a[t], &a[i]); } // printarray(a, n); }

     

  • 相关阅读:
    xdebug安装教程
    如何查看Linux操作系统的位数
    getconf命令【一天一个命令】
    redis 数据类型详解 以及 redis适用场景场合
    Redis和Memcache对比及选择
    无交换机实现集群网络互联
    性能调优攻略
    Chrome 插件集推荐
    在 Linux 下将 PNG 和 JPG 批量互转的四种方法
    Flashback for MySQL 5.7
  • 原文地址:https://www.cnblogs.com/lifan/p/3771063.html
Copyright © 2020-2023  润新知