1. 洗牌问题:
  2.  
  3. 洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样
  4. 高效率的实现乱序排列?
  5.  
  6. 关于洗牌问题,其实已经有了一个很好的shell解法,这里另外给三个基于AWK的方法,
  7. 有错误之处还请不吝指出。
  8.  
  9. 方法一穷举:
  10. 类似于穷举法,构造一个散列来记录已经打印行出现行的次数,如果出现次数多于一
  11. 次则不进行处理,这样可以防止重复,但缺点是加大了系统的开销。
  12.  
  13. awk -v N=`sed -n '$=' data` '
  14. BEGIN{
  15. FS="\n";
  16. RS=""
  17. }
  18. {
  19. srand();
  20. while(t!=N){
  21. x=int(N*rand()+);
  22. a[x]++;
  23. if(a[x]==)
  24. {
  25. print $x;t++
  26. }
  27. }
  28. }
  29. ' data
  30.  
  31. 方法二变换:
  32. 基于数组下标变换的办法,即用数组储存每行的内容,通过数组下标的变换
  33. 交换数组的内容,效率好于方法一。
  34.  
  35. #! /usr/awk
  36.  
  37. BEGIN{
  38. srand();
  39. }
  40.  
  41. {
  42. b[NR]=$;
  43. }
  44.  
  45. END{
  46.  
  47. C(b,NR);
  48. for(x in b)
  49. {
  50. print b[x];
  51. }
  52.  
  53. }
  54.  
  55. function C(arr,len,i,j,t,x){
  56.  
  57. for(x in arr)
  58. {
  59. i=int(len*rand())+;
  60. j=int(len*rand())+;
  61. t=arr[i];
  62. arr[i]=arr[j];
  63. arr[j]=t;
  64. }
  65.  
  66. }
  67.  
  68. 方法三散列:
  69.  
  70. 三个方法中最好的。
  71. 利用AWK中散列的特性(详细请看:info gawk 中的7.x ),只要构造一个
  72. 随机不重复的散列函数即可,因为一个文件每行的linenumber是独一无二的,所
  73. 以用:
  74.  
  75. 随机数+每行linenumber ------对应------> 那一行的内容
  76.  
  77. 即为所构造的随机函数。
  78. 从而有:
  79.  
  80. awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data
  81.  
  82. 其实大家担心的使用内存过大的问题不必太在意,可以做一个测试:
  83.  
  84. 测试环境:
  85. PM .4GHz CPU,40G硬盘,内存256MLAPTOP
  86. SUSE 9.3 GNU bash version 3.00. GNU Awk 3.1.
  87.  
  88. 产生一个五十几万行的随机文件,大约有38M
  89.  
  90. od /dev/urandom |dd count= >data
  91.  
  92. 拿效率较低的方法一来说:
  93.  
  94. 洗牌一次所用时间:
  95.  
  96. time awk -v N=`sed -n '$=' data` '
  97. BEGIN{
  98. FS="\n";
  99. RS=""
  100. }
  101. {
  102. srand();
  103. while(t!=N){
  104. x=int(N*rand()+);
  105. a[x]++;
  106. if(a[x]==)
  107. {
  108. print $x;t++
  109. }
  110. }
  111. }
  112. ' data
  113.  
  114. 结果(文件内容省略):
  115.  
  116. real 3m41.864s
  117. user 0m34.224s
  118. sys 0m2.102s
  119.  
  120. 所以效率还是勉强可以接受的。
  121.  
  122. 方法二的测试:
  123.  
  124. time awk -f awkfile datafile
  125.  
  126. 结果(文件内容省略):
  127.  
  128. real 2m26.487s
  129. user 0m7.044s
  130. sys 0m1.371s
  131.  
  132. 效率明显好于第一个。
  133.  
  134. 接着考察一下方法三的效率:
  135.  
  136. time awk 'BEGIN{srand()}{b[rand()NR]=$0}END{for(x in b)print b[x]}' data
  137.  
  138. 结果(文件内容省略):
  139.  
  140. real 0m49.195s
  141. user 0m5.318s
  142. sys 0m1.301s
  143.  
  144. 对于一个38M的文件来说已经相当不错了。
  145. 玩的愉快!

shell实现洗牌随机的更多相关文章

  1. 对数组排序进行"洗牌"(随机排序)

    这段代码在这里使用Fisher Yates洗牌算法给一个指定的数组进行洗牌(随机排序). function shuffle(arr) {     var i,        j,        tem ...

  2. Shell脚本实现乱序排列文件内容的多种方法(洗牌问题)

    洗牌问题:洗一副扑克,有什么好办法?既能洗得均匀,又能洗得快?即相对于一个文件来说怎样高效率的实现乱序排列? ChinaUnix 确实是 Shell 高手云集的地方,只要你想得到的问题,到那里基本上都 ...

  3. Hard 随机洗牌函数 @CareerCup

    第i个元素和index在[i,length-1]之间的一个数随机交换 package Hard; import CtCILibrary.AssortedMethods; /** * * Write a ...

  4. Craking the coding interview 面试题:完美随机洗牌

    给定一个序列,随机打乱这个序列,新产生的序列和任意一个序列产生的可能性是一样的,就是所谓的完美随机洗牌. 看下面的运行结果: 上面第一列是原数列,下面一行是新产生的打乱的数列. 基本思想:如果n-1个 ...

  5. 随机洗牌算法Knuth Shuffle和错排公式

    Knuth随机洗牌算法:譬如现在有54张牌,如何洗牌才能保证随机性.可以这么考虑,从最末尾一张牌开始洗,对于每一张牌,编号在该牌前面的牌中任意一张选一张和当前牌进行交换,直至洗到第一张牌为止.参考代码 ...

  6. 实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)

    实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例) 1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtup ...

  7. random array & shuffle 洗牌算法 / 随机算法

    random array & shuffle shuffle 洗牌算法 / 随机算法 https://en.wikipedia.org/wiki/Fisher–Yates_shuffle ES ...

  8. VB洗牌算法产生随机数组

    算法图示: 运行效果: 详细代码: Option Explicit '洗16张牌(0-15),方便用十六进制显示 Dim Card() As Long Private Sub 洗牌() Dim i&a ...

  9. 如何随机排序数组?使用多种方式!递归,迭代,洗牌,sort方法!

    方式1: 使用sort 方法 ---- // 方法1 使用sort 方法 var arr = [1,2,3,4,5,6,7,8]; function foo(arr) { var cloneArr = ...

随机推荐

  1. 【扩展欧几里得】poj2115 C Looooops

    题意大概是让你求(A+Cx) mod 2^k = B的最小非负整数解. 若(B-A) mod gcd(C,2^k) = 0,就有解,否则无解. 式子可以化成Cx + 2^k*y = B - A,可以用 ...

  2. struts-2-spring-2-jpa-ajax

    http://struts.apache.org/docs/struts-2-spring-2-jpa-ajax.html

  3. debian 6软件更新源列表

    deb http://ftp.debian.org/debian/ squeeze main non-free contribdeb http://ftp.debian.org/debian/ squ ...

  4. Queue 队列的用法

    队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. 以下实例演示了队 ...

  5. virtualenv、virtualenvwrapper安装和使用;Mac os的特殊性

    [sudo] pip install virtualenv 或者[sudo] pip3 install virtualenv [sudo]可用可不用 pip/pip3 install virtuale ...

  6. CMD一键获取cpu信息

    windows + R 输入cmd打开CMD 输入wmic cpu get Name 获取cpu名称-即物理cpu数 cpu get NumberOfCores获取cpu核心数 cpu get Num ...

  7. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.2.安装 cvuqdisk 软件包

    3.2.安装 cvuqdisk 软件包 3.2.1. 准备Oracle  Grid安装包 上传Grid .Oracle 安装文件: sftp> put E:\Software\linux.x64 ...

  8. LeetCode(28)Implement strStr()

    题目 Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if nee ...

  9. 【千纸诗书】—— PHP/MySQL二手书网站后台开发之基础知识

    前言: 在具体回顾每一个功能的实现前,还是有必要先温习一些项目涉及到的PHP.MySQL[语法基础].项目github地址:https://github.com/66Web/php_book_stor ...

  10. Linux 部署ftp报530 错误解决方案

    sudo apt-get remove vsftpdsudo rm /etc/pam.d/vsftpdsudo apt-get install vsftpd 这是因为ubuntu启用了PAM,所在用到 ...