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

  • 相关阅读:
    算法学习【第2篇】:列表查找以及二分查找
    算法学习【第1篇】:算法之基础
    九、爬虫框架之Scrapy
    八、asynicio模块以及爬虫应用asynicio模块(高性能爬虫)
    第七篇:爬虫实战— 4、爬取校花网视频示例(点开往下拉)
    第七篇:爬虫实战— 3、自动登录123并且自动发送邮箱;自动爬取京东商品信息
    第七篇:爬虫实战—2、投递拉钩网简历
    第七篇:爬虫实战--- 1、破解滑动验证码
    Ubuntu安装JDK与环境变量配置
    显示 Ubuntu 11.10 的 终端窗口
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4410319.html
Copyright © 2011-2022 走看看