• 浅谈php随机不重复数的两种算法


    先引入别人的一个秒表计时类(counttime.class.php):

    1.先看第一个例子(大数中取少数):

     1 <?
     2 /*
     3 @描述: Stopwatch这个类用户获取脚本执行时间
     4 @作者: Klesti Hoxha <klesti@gmail.com>
     5 */
     6 
     7 class Stopwatch {
     8 private $start;
     9 private $end;
    10 private $markup_start = array();
    11 private $markup_end = array();
    12 
    13 function __construct($markup=false) {
    14 $this->start($markup);
    15 }
    16 
    17 public function start($markup=false) {
    18 if (!$markup) {
    19 $this->start = $this->getmicrotime();
    20 } else {
    21 $this->markup_start[$markup] = $this->getmicrotime();
    22 }
    23 }
    24 
    25 public function stop($markup=false) {
    26 if (!$markup) {
    27 $this->end = $this->getmicrotime();
    28 } else {
    29 $this->markup_end[$markup] = $this->getmicrotime();
    30 }
    31 return $this->getDuration($markup);
    32 }
    33 
    34 public function getDuration($markup=false) {
    35     if (!$markup)
    36      {
    37         return number_format($this->end-$this->start,4);
    38     } else {
    39         return number_format($this->markup_end[$markup]-$this->markup_start[$markup],4);
    40     }
    41 }
    42 
    43 public function reset($markup) {
    44 if (!$markup) {
    45 $this->start = 0;
    46 $this->end = 0;
    47 $this->markup_start = array();
    48 $this->markup_end = array();
    49 } else {
    50 $this->markup_start[$markup] = 0;
    51 $this->markup_end[$markup] = 0;
    52 }
    53 }
    54 
    55 private function getmicrotime(){
    56 list($usec, $sec) = explode(" ",microtime());
    57 return ((float)$usec + (float)$sec);
    58 }
    59 
    60 }
    61 ?>

    测试的两种方法如下:

     1 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     2 <?php
     3 require "counttime.class.php";//把类文件引用进来,根据你的实际情况来确定路径,这里是在同级目录
     4 $s = new Stopwatch();
     5 
     6 $s->start("section1");
     7 //range 是将1到100 列成一个数组
     8 $numbers = range (1,1000000);
     9 //shuffle 将数组顺序随即打乱
    10 shuffle ($numbers);
    11 //array_slice 取该数组中的某一段
    12 $no=30;
    13 $result = array_slice($numbers,0,$no);
    14 for ($i=0;$i<$no;$i++){
    15 echo $result[$i]."<br/>";
    16 }
    17 echo "第一个测验方法结束<br/><br/>";
    18 $s->stop("section1");
    19 
    20 $s->start("section2");
    21 function unique_rand($min, $max, $num)
    22 {
    23         $count = 0;
    24         $return = array();
    25         while ($count < $num) {
    26             $return[] = mt_rand($min, $max);
    27             $return = array_flip(array_flip($return));
    28             $count = count($return);
    29         }
    30         shuffle($return);
    31         return $return;
    32 }
    33 
    34     $arr = unique_rand(1, 100000000000, 30);
    35     $result = '';
    36     for($i=0; $i < count($arr);$i++)
    37     {
    38         $result = $arr[$i];
    39         echo $result."<br/>";
    40     }
    41     $s->stop("section2");
    42 
    43 
    44 //输出时间
    45 echo "Section 1 Duration: " . $s->getDuration("section1") . " seconds.<br/>";
    46 echo "Section 2 Duration: " . $s->getDuration("section2") . " seconds.<br/>";
    47 ?>

    结果为:

     1 413537
     2 198587
     3 60611
     4 599544
     5 946241
     6 462853
     7 570943
     8 980260
     9 717416
    10 969324
    11 292403
    12 614443
    13 769469
    14 151951
    15 167883
    16 308727
    17 342706
    18 955659
    19 112311
    20 329008
    21 182668
    22 330600
    23 921966
    24 993143
    25 369227
    26 747066
    27 793185
    28 347872
    29 439016
    30 428600
    31 第一个测验方法结束
    32 
    33 649589727
    34 450823813
    35 324717181
    36 44553762
    37 375669657
    38 37128612
    39 25135327
    40 468454185
    41 73395357
    42 753960006
    43 214455797
    44 5367614
    45 1153263961
    46 17803441
    47 669057198
    48 55366324
    49 1117343950
    50 203530485
    51 1160930064
    52 326487914
    53 565471236
    54 7068443
    55 846955001
    56 832037489
    57 1067813034
    58 219239595
    59 1069795964
    60 1049898846
    61 926301266
    62 197341539
    63 Section 1 Duration: 0.5800 seconds.
    64 Section 2 Duration: 0.0000 seconds.

    结论:对于从大量数据中取少量数据,显然第二种比较快。

    2.在来看看从大数中取大数:

     1 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     2 <?php
     3 require "counttime.class.php";//把类文件引用进来,根据你的实际情况来确定路径,这里是在同级目录
     4 $s = new Stopwatch();
     5 
     6 $s->start("section1");
     7 //range 是将1到100 列成一个数组
     8 $numbers = range (1,1000000);
     9 //shuffle 将数组顺序随即打乱
    10 shuffle ($numbers);
    11 //array_slice 取该数组中的某一段
    12 $no=10000;
    13 $result = array_slice($numbers,0,$no);
    14 for ($i=0;$i<$no;$i++){
    15 echo $result[$i]."<br/>";
    16 }
    17 echo "第一个测验方法结束<br/><br/>";
    18 $s->stop("section1");
    19 
    20 $s->start("section2");
    21 function unique_rand($min, $max, $num)
    22 {
    23         $count = 0;
    24         $return = array();
    25         while ($count < $num) {
    26             $return[] = mt_rand($min, $max);
    27             $return = array_flip(array_flip($return));
    28             $count = count($return);
    29         }
    30         shuffle($return);
    31         return $return;
    32 }
    33 
    34     $arr = unique_rand(1, 1000000, 10000);
    35     $result = '';
    36     for($i=0; $i < count($arr);$i++)
    37     {
    38         $result = $arr[$i];
    39         echo $result."<br/>";
    40     }
    41     $s->stop("section2");
    42 
    43 
    44 //输出时间
    45 echo "Section 1 Duration: " . $s->getDuration("section1") . " seconds.<br/>";
    46 echo "Section 2 Duration: " . $s->getDuration("section2") . " seconds.<br/>";
    47 ?>

    输出结果为:

    1 前面省略………………
    2 Section 1 Duration: 0.6050 seconds.
    3 Section 2 Duration: 17.4260 seconds.

    结论:对于第一种方法输出一个数据的时间,跟大数的数字时间差不多。但是第二个时间显然耗费得要离谱。达到了17.5秒。

    总结:

    1.翻翻法对于选少量数据好用,大量数据就会比较吃力。

  • 相关阅读:
    codeblocks多文件联合编译
    C++顶层const和底层const的区别
    keras failed to create cublas handle:CUBLAS_STATUS_ALLOC_FAILED问题
    Notepad++强大的代码补全和代码提示功能的方法
    PEP8编码风格
    在Maven项目中使用easypoi完成Excel文件上传下载
    Restful风格,使用同一地址,访问不同的方法
    注解@NoRepositoryBean的作用
    注解@MappedSuperclass的作用
    Shiro整合Spring以及权限登陆过滤
  • 原文地址:https://www.cnblogs.com/soongkun/p/4279720.html
Copyright © 2020-2023  润新知