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

  • 相关阅读:
    js 闭包
    js 图片放大镜功能
    前端页面优化
    css 背景图片自适应分辨率大小 兼容
    纯css实现箭头
    js 排序算法
    css3 渐变 兼容
    css 兼容性总结
    css3 @keyframe 抖动/变色动画
    关于$.data(element,key,value)与ele.data.(key,value)的区别
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4410319.html
Copyright © 2011-2022 走看看