• 洗牌算法分析


    洗牌问题:给定函数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); }

     

  • 相关阅读:
    二叉排序树
    C# 大端与小端
    【转】C#socket通信
    【转】Github 搜索技巧,快速找到好资源
    web api 跨域请求,ajax跨域调用webapi
    【转】Linux简介及最常用命令
    【转】带你吃透RTMP
    09-vuex基本应用之计数demo
    08-配置vue路由的步骤
    02-原型与原型链
  • 原文地址:https://www.cnblogs.com/lifan/p/3771063.html
Copyright © 2020-2023  润新知