zoukankan      html  css  js  c++  java
  • 2.7 洗牌算法

    出自数据结构与算法分析--C语言描述 习题2.7

    在有个函数int rand(int n)返回1-n之间的随机数。如何把数组A[N]打乱?

    最初的Fisher–Yates算法是在另外开辟一个数组B[N],把打算后的A[N]放到B[N]中,步骤如下

    设i=0

    1、生成1-A.length长度之间的随机数k

    2、把A[k]放到B[i],去除数组A中的A[k],i++。

    3、如果A.length>0,转到第1步。

    这个算法要去除A中的数,每次要移位,所以算法复杂度为O(N^2)。

    例如一个算法过程如下:

    随机数范围随机数AB  
        1 2 3 4 5 6 7 8  
    随机数范围随机数AB
    1–8 3 1 2 3 4 5 6 7 8 3
    随机数范围随机数AB
    1–7 4 1 2 3 4 5 6 7 8 3 5
    随机数范围随机数AB
    1–6 5 1 2 3 4 5 6 7 8 3 5 7
    1–5 3 1 2 3 4 5 6 7 8 3 5 7 4
    1–4 4 1 2 3 4 5 6 7 8 3 5 7 4 8
    1–3 1 1 2 3 4 5 6 7 8 3 5 7 4 8 1
    1–2 2 1 2 3 4 5 6 7 8 3 5 7 4 8 1 6
        1 2 3 4 5 6 7 8 3 5 7 4 8 1 6 2

    后来算法有了改进,不是另外开辟数组,而是来交换数组A上面的元素来达到重排。

    这个算法有2个版本,原理一样:

    版本1:

    [cpp] view plaincopy
     
    1. for(int i = n; i>=1; --i)  
    2. {  
    3.     int j=rand(i);//生成1-i之间的随机数  
    4.     exchange(A[i],A[j]);//交换A[i],A[j]  
    5. }  


    版本2:

    [cpp] view plaincopy
     
    1. for(int i = 1; i <= n; ++i)  
    2. {  
    3.     int j=(rand(n)/n)*(n-i+1)+i-1;//生成i-n之间的随机数  
    4.     exchange(A[i],A[j]);//交换A[i],A[j]  

    版本1的一个演算过程如下:

    Modern method[edit]

    We'll now do the same thing using Durstenfeld's version of the algorithm: this time, instead of striking out the chosen numbers and copying them elsewhere, we'll swap them with the last number not yet chosen. We'll start by writing out the numbers from 1 to 8 as before:

    RangeRollScratchResult
        1 2 3 4 5 6 7 8  

    For our first roll, we roll a random number from 1 to 8: this time it's 6, so we swap the 6th and 8th numbers in the list:

    RangeRollScratchResult
    1–8 6 1 2 3 4 5 8 7 6

    The next random number we roll from 1 to 7, and turns out to be 2. Thus, we swap the 2nd and 7th numbers and move on:

    RangeRollScratchResult
    1–7 2 7 3 4 5 8 2 6

    The next random number we roll is from 1 to 6, and just happens to be 6, which means we leave the 6th number in the list (which, after the swap above, is now number 8) in place and just move to the next step. Again, we proceed the same way until the permutation is complete:

    RangeRollScratchResult
    1–6 6 1 7 3 4 5 8 2 6
    1–5 1 5 7 3 4 1 8 2 6
    1–4 3 5 7 4 3 1 8 2 6
    1–3 3 5 7 4 3 1 8 2 6
    1–2 1 7 5 4 3 1 8 2 6



    参考:http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

  • 相关阅读:
    hibernate怎么做分页
    JS+CSS带数字和左右按钮可控制切换的图片幻灯
    AOP下的权限控制实现
    Hibernate3和MyBatis(iBatis)的执行效率比较
    CKEditor/FCKEditor 使用-CKeditor 3.0.1 快速教程(含插入图片)
    用JS写CSS
    spring aop实现权限控制,路径控制
    sql server 同步复制要点
    千万别把自己当人才
    web.xml元素介绍
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4410319.html
Copyright © 2011-2022 走看看